tags:

views:

338

answers:

3

I'm writing a function that takes an Enum and casts it to uint. From what I've seen when casting to int, you have to cast it to an object first: (int) (object) myEnumValue. If you write (int) myEnumValue you get a compile time exception.

Now, when I tried to cast it to uint, I was expecting that (uint) (object) myEnumValue would be alright. It compiles nicely, but when run, it generates an InvalidCastException. So to get it to work, I've used

(uint) (int) (object) myEnumValue

I think it looks funny, so I'm quite happy, but why is it so?

Maybe it would have been more correct to ask why it is not possible to cast object to uint, but I'm interested in whether there is another way to go from an Enum to uint. Is there?

Edit:

The context is a function, something like this:

public static uint ToUInt (Enum e)
{
    return (uint) (int) (object) e;
}

Edit 2:

The best solution was as mentioned by thecoop:

Convert.ToUInt32(e)
+9  A: 

The (uint) (object) myEnum approach fails because, by default, C# enums use int as their underlying type, and an int is what they get turned into when they're boxed. The C# syntax makes it look like enums inherit from their underlying type (like enum MyEnum : uint).

You have to explicitly tell the compiler to unbox from object to int first, then do a numerical conversion from int to uint. (Even though the syntax is the same, unboxing from object to a value type is a different process from casting between int and uint.)

Tim Robinson
Ok, so if I specify my Enum as Enum : uint, it would be the other way around?
Jonatan Lindén
@Jonatan: yes, that would box the enum as uint, and you would be forced to unbox as uint.
Martinho Fernandes
That's right: (uint) e will be fine, but (int) e will blow up.
Tim Robinson
@Tim: inherit is a wrong term. You cannot inherit from `System.Int32` (maybe you can with some voodoo black magic, but that's not relevant). Enums inherit from `System.Enum`. What's correct to say is that the underlying type is `int`.
Martinho Fernandes
Er, you're right. And in this situation, what matters is that the enum is boxed to an int.
Tim Robinson
What about using `Convert.ToUInt32`? This would be much easier to read...
thecoop
@thecoop, yes, and this could be the only practical way if you're not sure whether you're dealing with an int or a uint. Add your own answer and I'll upvote you :)
Tim Robinson
+4  A: 

From what I've seen when casting to int, you have to cast it to an object first: (int) (object) myEnum. If you write (int) myEnum you get a compile time exception.

Not true. You can directly cast an enum value to an integer type.

Now, when I tried to cast it to uint, I was expecting that (uint) (object) myEnum would be alright. It compiles nicely, but when run, it generates an InvalidCastException. So to get it to work, I've used: (uint) (int) (object) myEnum
I think it looks funny, so I'm quite happy, but why is it so?

When you cast an enum value to object, it'll be boxed as its underlying type, which is int by default. You cannot unbox a boxed value to any type other than its actual type directly. Even this will fail:

short s = 10;
object o = s;
int i = (int)o; // throws `InvalidCastException` while `int i = (int)s;` works.
Mehrdad Afshari
A: 

In case you need to go in the opposite direction, that is, from an underlying type to the enumeration of a particular type:

enum MyEnumType { a, b, c };
//...
MyEnumType enum_val = (MyEnumType)Enum.ToObject(typeof(MyEnumType), 2);
Console.WriteLine(enum_val == MyEnumType.c);
// "True"

I found this to be necessary (rather than simple casting) when authoring generic types. Since you can't use 'where' clauses to sufficiently constrain the generic <T> to your enumeration type, the compiler won't let you cast a numeric to it.

Glenn Slayden