2015-08-05 3 views
6

Я написал код ниже и успешно компилируется.Могу ли я создать конструктор для Enum?

class Program 
{ 
     enum Fruits 
     { 
      Apple, 
      Mango, 
      Banana 
     } 

     static void Main(string[] args) 
     { 
      Fruits f = new Fruits(); 
     } 
} 

Несмотря на Fruits, представляющее собой enum, компилятор и интерпретатор разрешают мне писать это. Означает ли это, что я могу создать конструктор для перечисления? если да, то как?

+1

Что бы вы хотели сделать с помощью такого конструктора? –

+1

Возможно, я захочу переопределить его поведение по умолчанию возвращения Apple по умолчанию, просто задумываясь вслух. – yogi

+0

Вы можете изменить значение по умолчанию, изменив порядок, в котором перечислены альтернативы перечисления. –

ответ

4

Нет, вы не можете.

new Fruits() будет возвращать значение по умолчанию (значение, соответствующее 0 в базовом типе перечисления), это то же самое, как default(Fruits) (или Fruits.Apple в вашем случае).

Помните, что перечисления представляют собой только обертки вокруг примитивного типа (int по умолчанию). Вы можете в значительной степени сравнить new Fruits() с new int().

Обычно вы не используете синтаксис new Fruits()/new int(), как это чаще просто написать 0 или default(T), но вы можете использовать его в общий код. В качестве примера:

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

Вы разрешили позвонить NewInstance<Fruits>(), который будет возвращать Fruits.Apple.

+0

Синтаксический сахар в 'int' –

+1

' int() 'работает в .NET 1.0, до дженериков. Это преимущество, но не причина. –

+0

@Jon Спасибо за ваш вклад, я полностью забыл .NET 1.0. Я переформулировал ответ. –

1

No. Проверьте вывод 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 нормального класса. Посмотрите на IL_001 в разделе Program.Main, где он фактически вызывает конструктор для класса.

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   
3

C# Spec:

типа перечисление является отдельным типом значения с набором именованных констант.

Что касается значения по умолчанию (как описано в другом ответе):

Значение по умолчанию любого типа перечисления является неотъемлемым нулевым значением преобразуется к типу перечисления. В случаях, когда переменные автоматически присваиваются значениям , это значение, присвоенное переменным типов перечислений. Для того, чтобы значение по умолчанию для типа перечисления было легко доступно, буквальное значение 0 неявно преобразуется в любой тип перечисления.

Переместить константу по умолчанию, чтобы она была первой в вашем перечислении.

1

Для любого типа значений существует конструктор без параметров, который возвращает значение all-zero. Следовательно:

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 

Однако:

  1. Вы не можете добавить новый конструктор типа, который не является struct или class, и так далеко, как ценностные типы идут, только struct.
  2. Вы не можете изменить реализацию любого из этих конструкторов по умолчанию.

В случае enum и примитивов конструктор даже не объявлен.

Следовательно, вы не можете создать такой конструктор.

(Строго говоря, .NET позволяет установить определенный конструктор без параметров без кода struct, но C# не делает этого, и если вы делаете это в необработанном CIL, существуют противоречивые правила относительно того, когда он будет вызван, и когда вы 'просто получить экземпляр all-zero, созданный).

Смежные вопросы