Reputation: 3967
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
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
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
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