Rémi
Rémi

Reputation: 3967

int to enum invalid conversion

I was testing a bit of code I wrote and was wondering if a default case handling was needed.

Lets define MyEnum like this

public enum MyEnum 
{
    [Description("Value")]
    Value = 0,
    [Description("Other value")]
    OtherValue = 1,
}

the logic I was asking myself about was similar to this one :

MyEnum val = (MyEnum)8;
if(val == MyEnum.Value)
    //do stuff
else if (val == MyEnum.OtherValue)
    //do other stuff
else 
    throw new ArgumentException("The value is not currently supported");

My reasoning was to not have a default case because the cast from a value not defined in the Enum would throw an exception anyway before even being caught by my piece of code.

So I tryed with the exemple I have up here and at my suprise the cast didn't threw any exception and it was my default case handling witch threw the exception.

My question is : Why is the cast of any int to MyEnum is valid? I understand that in this exemple the underlying value of the Enum is int but I would have expected an exception to been thrown from the cast. Why is that Valid?

Upvotes: 2

Views: 371

Answers (3)

Daniel Brückner
Daniel Brückner

Reputation: 59645

Enumerations are just a fancy way to work with values of the underlying datatype - Int32 by default. You get named values, you lose mathematical operations. There is no rule that only values named in the declaration are valid values and therefore you get no exception or compiler error.

This becomes really obvious when you use enumerations as flags.

[Flags]
public enum Something
{
   Foo = 1,
   Bar = 2,
   Baz = 4
}

Now something like this

var x = Something.Foo | Something.Bar; // The value is 1 | 4 = 5

is absolutely fine and again you can have values you never named. It all boils down to your wrong assumption that the set of allowed values is in someway restricted and as pointed out by other answers referring to the specification this is just not the case.

Upvotes: 4

Sergey Berezovskiy
Sergey Berezovskiy

Reputation: 236228

That is by design. See C# specification 4.1.9 Enumeration types:

An enumeration type is a distinct type with named constants. The set of values of the enumeration type is the same as the set of values of the underlying type. Values of the enumeration type are not restricted to the values of the named constants.

Actually enumeration is just a set of named literal fields (which are named constants of enumeration type) and one special field which holds enum instance value:

.class public auto ansi sealed MyEnum
    extends [mscorlib]System.Enum  
{
    .field public static literal valuetype Namespace.MyEnum Value = int32(0)
    .field public static literal valuetype Namespace.MyEnum OtherValue = int32(1)
    .field public specialname rtspecialname int32 value__
}

As you can see this is a simple filed of underlying type, and any Int32 value can be assigned to enum variable.

Upvotes: 1

Lee
Lee

Reputation: 144136

The spec describes this behaviour:

14.5 Enum values and operations

The set of values that an enum type can take on is not limited by its enum members. In particular, any value of the underlying type of an enum can be cast to the enum type, and is a distinct valid value of that enum type.

Upvotes: 0

Related Questions