Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Casting ints to enums in C#

Tags:

c#

enums

casting

There is something that I cannot understand in C#. You can cast an out-of-range int into an enum and the compiler does not flinch. Imagine this enum:

enum Colour {     Red = 1,     Green = 2,     Blue = 3 } 

Now, if you write:

Colour eco; eco = (Colour)17; 

The compiler thinks that’s fine. And the runtime, too. Uh?

Why did the C# team decide to make this possible? This decision misses the point of using enums, I think, in scenarios like this:

void DoSomethingWithColour(Colour eco) {     //do something to eco. } 

In a strong-typed language like C#, I would like to assume that eco will always hold a legal Colour value. But this is not the case. A programmer could call my method with a value of 17 assigned to eco (as in previous code snippet), so the code in my method must not assume that eco holds a legal Colour value. I need to test for it explicitly and handle the exceptional values as I please. Why is this?

In my humble opinion, it would be much nicer if the compiler issued an error (or even a warning) message when casting an out-of range int into an enum, if the int value is known at compile time. If not, the runtime should throw an exception at the assignment statement.

What do you think? Is there any reason why this is so?

(Note. This is a question I posted ages ago on my blog but got no informative response.)

like image 513
CesarGon Avatar asked Nov 18 '09 19:11

CesarGon


People also ask

Can I cast int to enum?

You can explicitly type cast an int to a particular enum type, as shown below.

Can you cast an enum in C?

Yes. In C enum types are just int s under the covers. Typecast them to whatever you want. enums are not always ints in C.

Can enums be ints?

The enum can be of any numeric data type such as byte, sbyte, short, ushort, int, uint, long, or ulong. However, an enum cannot be a string type.

Can we assign value to enum in C?

An enum is considered an integer type. So you can assign an integer to a variable with an enum type.


2 Answers

Guessing about 'why' is always dangerous, but consider this:

enum Direction { North =1, East = 2, South = 4, West = 8 } Direction ne = Direction.North | Direction.East;  int value = (int) ne; // value == 3 string text = ne.ToString();  // text == "3" 

When the [Flags] attribute is put in front of the enum, that last line changes to

string text = ne.ToString();  // text == "North, East" 
like image 60
Henk Holterman Avatar answered Sep 25 '22 06:09

Henk Holterman


Not sure about why, but I recently found this "feature" incredibly useful. I wrote something like this the other day

// a simple enum public enum TransmissionStatus {     Success = 0,     Failure = 1,     Error = 2, } // a consumer of enum public class MyClass  {     public void ProcessTransmissionStatus (TransmissionStatus status)     {         ...         // an exhaustive switch statement, but only if         // enum remains the same         switch (status)         {             case TransmissionStatus.Success: ... break;             case TransmissionStatus.Failure: ... break;             case TransmissionStatus.Error: ... break;             // should never be called, unless enum is              // extended - which is entirely possible!             // remember, code defensively! future proof!             default:                 throw new NotSupportedException ();                 break;         }         ...     } } 

question is, how do I test that last case clause? It is completely reasonable to assume someone may extend TransmissionStatus and not update its consumers, like poor little MyClass above. Yet, I would still like to verify its behaviour in this scenario. One way is to use casting, such as

[Test] [ExpectedException (typeof (NotSupportedException))] public void Test_ProcessTransmissionStatus_ExtendedEnum () {     MyClass myClass = new MyClass ();     myClass.ProcessTransmissionStatus ((TransmissionStatus)(10)); } 
like image 45
johnny g Avatar answered Sep 23 '22 06:09

johnny g