我可以为Enum创建构造函数吗?
我写了下面的代码,它正在成功编译。
class Program { enum Fruits { Apple, Mango, Banana } static void Main(string[] args) { Fruits f = new Fruits(); } }
尽管Fruits
是一个enum
,编译器和解释器允许我写这个。 这是否意味着我可以为枚举创建构造函数? 如果是,那怎么样?
不,你不能。
new Fruits()
将返回默认值(枚举的基础类型中对应于0
的值),它与default(Fruits)
(或您的案例中的Fruits.Apple
)相同。
请记住,枚举只是原始类型的包装(默认为int
)。 您可以将new Fruits()
与new int()
。
通常你不使用new Fruits()
/ new int()
语法,因为它只是写0
或default(T)
更常见,但你可能想在通用代码中使用它。 举个例子:
public T NewInstance() where T : new() { return new T(); }
您可以调用NewInstance
,它将返回Fruits.Apple
。
C#规格 :
枚举类型是具有一组命名常量的不同值类型。
至于默认值(如另一个答案中所述):
任何枚举类型的默认值是转换为枚举类型的整数值零。 在变量自动初始化为默认值的情况下,这是给予枚举类型变量的值。 为了使枚举类型的默认值易于使用,文字0隐式转换为任何枚举类型。
将默认常量移动到枚举中的第一个。
不。查看IL输出(在LINQPad中生成)。 它根本不是在调用构造函数。 相反,它将整数值0存储在名为f
的局部变量中。 这与您对枚举使用类型转换时获得的输出完全相同 。
就编译器而言, Fruits f = new Fruits();
与Fruit f = (Fruit)0;
。
Fruits f = new Fruits()
IL
Program.Main: IL_0000: nop IL_0001: ldc.i4.0 IL_0002: stloc.0 // f IL_0003: ret Program..ctor: IL_0000: ldarg.0 IL_0001: call System.Object..ctor IL_0006: ret
为了比较,这是正常类的IL输出。 查看Program.Main下的IL_001,它实际上调用了该类的构造函数。
Program.Main: IL_0000: nop IL_0001: newobj UserQuery+Program+Fruits..ctor IL_0006: stloc.0 // f IL_0007: ret Program..ctor: IL_0000: ldarg.0 IL_0001: call System.Object..ctor IL_0006: ret Fruits..ctor: IL_0000: ldarg.0 IL_0001: call System.Object..ctor IL_0006: ret
对于任何值类型,都有一个无参数构造函数,它返回全零值。 因此:
var val = new int(); // 0 var val = new double(); // 0.0 var val = new DateTime(); // 0001-01-01T00:00:00.000000 Unspecified timezone var val = new StringSplitOptions(); // StringSplitOptions.None
然而:
- 您不能为不是
struct
或class
的类型添加新的构造struct
,因此就value-types而言,只有struct
。 - 您无法更改任何这些默认构造函数的实现。
在enum
和原语的情况下,甚至没有声明构造函数。
因此,您无法创建这样的构造函数。
(严格来说,.NET确实允许你在一个struct
上设置一个已定义的无参数构造struct
但是C#没有,如果你在原始CIL中执行它,那么它将被调用的时间和你什么时候才会得到不一致的规则创建了一个全零实例)。