Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.NET: Why aren't Enum's Range/Value Checked?

Tags:

.net

enums

This has always bugged me. Perhaps someone with some hardcore knowledge of .NET internals can explain it to me.

Suppose I define an enum as follows:

public enum Foo
{
   Eenie = 1,
   Meenie = 2,
   Miney = 3,
   Moe = 4
}

Now, also suppose that somewhere in my code, I have the following code:

int bar = (Foo)5;

This will compile just fine, and no exception will be raised whatsoever, even though the value 5 is clearly not a valid value defined in Foo.

Or, consider the following:

public void ProcessFoo(Foo theFoo)
{
    // Do processing
}

public static void Main()
{
    ProcessFoo((Foo)5);
}

Again, no exception.

In my mind, this should result in a type mismatch exception, because 5 is not a Foo. But the designers chose not to do that.

Now, I've written an extension method that can verify that this is the case, and it's no big deal to invoke it to ensure that that's the case, but I have to use reflection to do it (with all its performance penalties and whatnot).

So again, what compelling reason is there that could possibly have driven the decision to not have a checked enum?

For reference, from the MSDN documentation for the Enum class:

When you define a method or property that takes an enumerated constant as a value, consider validating the value. The reason is that you can cast a numeric value to the enumeration type even if that numeric value is not defined in the enumeration.

like image 970
Mike Hofer Avatar asked Jan 11 '09 13:01

Mike Hofer


2 Answers

The issue was performance. It is quite simple to have a checked enum for normal enums such as Color

enum Color {
  Red,
  Blue
}

The problem though is for enum's which are used as bit flags.

enum Property {
  IsFirst = 0x1,
  IsDefault = 0x2,
  IsLastAccessed = 0x4
}

Having to do a bitwise check for every single integer which is converted to an Enum value was deemed to be too expensive. Hence the relaxed conversion to enum values.

like image 142
JaredPar Avatar answered Oct 23 '22 08:10

JaredPar


Range-checking has a potentially unnecessary cost. It's therefore reasonable to not perform it implicitly. As already mentioned, [Flags] require that no such checking takes place. If the runtime would check for the presence of [Flags], this would still incur a runtime penalty every time you perform a conversion.

The only way around this would be for the compiler to be aware of the [Flags] attribute. I guess this wasn't done to reduce the amount of runtime knowledge hardcoded into the compiler.

like image 30
Konrad Rudolph Avatar answered Oct 23 '22 06:10

Konrad Rudolph