在学习泛型的过程中,我开始了解类型参数的约束。其中一个约束是new()约束。根据微软的说法:
type参数必须具有公共无参数构造函数。与其他约束一起使用时,必须最后指定new()约束。
现在我有这样的代码。
using System;
namespace Test
{
class A { }
struct S { }
enum E { }
class Generics
{
public static void GenericMethod<T>() where T : new()
{
}
}
class Program
{
static void Main(string[] args)
{
Generics.GenericMethod<A>(); // Line 1
Generics.GenericMethod<S>(); // Line 2
Generics.GenericMethod<E>(); // Line 3
}
}
}
为什么new()约束允许枚举作为类型参数传递?
我也能做到这一点
E e = new E();
在上面的代码中。
这是否意味着默认情况下枚举具有无参数构造函数?
编辑:阅读答案和评论后,我认为枚举包含默认构造函数。所以我用反射来看看我是否可以在控制台上打印枚举E的默认构造函数。代码如下
Type T = typeof(E);
Console.WriteLine("Constructors");
ConstructorInfo[] constructors = T.GetConstructors();
foreach (var constructor in constructors)
{
Console.WriteLine(constructor.ToString());
}
但它不会打印任何东西。
所以问题仍然存在。枚举是否有默认的无参数构造函数?
这是允许的,因为所有特定的枚举类型都是value types。因此,C#为它们提供了一个默认构造函数:
每个值类型都有一个隐式默认构造函数,用于初始化该类型的默认值。
每个值类型T
都允许使用约束where T : new()
,包括每个枚举类型。
使用new T()
时,它对应于值类型的零值。对于值类型,它与default(T)
相同。
有一个更具体的约束,where T : struct
,也允许枚举类型(但不是Nullable<>
)。由于where T : new()
自动包含struct
,因此该约束“暗示”new()
,因为您无法指定两者。同样,在值类型的情况下,new T()
与default(T)
相同。
编辑:解决新问题:
枚举是否具有默认参数构造函数?
不,实际上值类型(包括枚举)没有这个零参数实例构造函数。但仍然允许使用语法new E()
,并产生与default(E)
相同的“零”值。并且特别允许将值类型用于约束到T
的通用参数where T : new()
。
请参阅相关主题Why default constructor does not appear for value types?