yogi
yogi

Reputation: 19591

Can I create constructor for Enum?

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?

Upvotes: 10

Views: 14808

Answers (4)

Lucas Trzesniewski
Lucas Trzesniewski

Reputation: 51330

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.

Upvotes: 7

Ofiris
Ofiris

Reputation: 6141

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.

Upvotes: 4

Jon Hanna
Jon Hanna

Reputation: 113222

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).

Upvotes: 1

just.another.programmer
just.another.programmer

Reputation: 8785

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         

Upvotes: 1

Related Questions