Can I create constructor for Enum?

匿名 (未验证) 提交于 2019-12-03 00:48:01

问题:

I have written below code and it's compiling successfully.

class Program {         enum Fruits         {             Apple,             Mango,             Banana         }          static void Main(string[] args)         {             Fruits f = new Fruits();         } }

Despite of Fruits being an enum, compiler and interpreter are allowing me to write this. Does this mean I can create a constructor for an enum? if yes then how?

回答1:

No, you can't.

new Fruits() will return the default value (the value corresponding to 0 in the underlying type of the enum), it's the same as default(Fruits) (or Fruits.Apple in your case).

Remeber that enums are only wrappers around a primitive type (int by default). You can pretty much compare new Fruits() to new int().

Usually you don't use the new Fruits()/new int() syntax as it's more common to just write 0 or default(T), but you may want to use it in generic code. As an example:

public T NewInstance<T>()     where T : new() {     return new T(); }

You are allowed to call NewInstance<Fruits>(), which will return Fruits.Apple.



回答2:

C# Spec:

An enum type is a distinct value type with a set of named constants.

As for the default value (as explained in the other answer):

The default value of any enum type is the integral value zero converted to the enum type. In cases where variables are automatically initialized to a default value, this is the value given to variables of enum types. In order for the default value of an enum type to be easily available, the literal 0 implicitly converts to any enum type.

Move the default constant to be the first in your enum.



回答3:

No. Check out the IL output (generated in LINQPad). It's not actually calling a constructor at all. Instead, it's storing the integer value 0 inside a local variable called f. This is the exact same output as you get when you use a type cast to the enum.

As far as the compiler is concerned, Fruits f = new Fruits(); is the same as 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   

For comparison, here's the IL output of a normal class. Look at IL_001 under Program.Main where it actually calls a constructor for the class.

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         


回答4:

For any value type, there is a parameterless constructor that returns the all-zero value. Hence:

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

However:

  1. You cannot add a new constructor for a type that isn't a struct or a class, and so as far as value-types go, only struct.
  2. You cannot change the implementation of any of these default constructors.

In the case of enums and primitives the constructor isn't even declared.

Hence you can't create such a constructor.

(Strictly speaking, .NET does allow you to set a defined parameterless constructor on a struct but C# doesn't, and if you do it in raw CIL there are inconsistent rules as to when it will be called and when you'll just get an all-zero instance created).



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!