I have an enum, Foo:
public enum Foo { Alpha, Bravo, Charlie }
If I attempt the following cast from a boxed int to a Foo?, I get an InvalidCastException:
var x = (Foo?)(object)1;
This led me to some experimentation...
var x = (Foo)(object)1; // succeeds
var x = (long)(object)1; // fails
var x = (long?)(object)1; // fails
var x = (long)1; // succeeds
var x = (long?)1; // succeeds
var x = (int)(object)1; // succeeds
var x = (int?)(object)1; // succeeds
What this tells me is that you can cast from a boxed int to an enum but not to a long, and you cannot convert from a boxed int to any kind of nullable except an int?.
By the way, the reason I'm casting the int to object first is that I'm really trying to cast from an int to a generic parameter TValue, like this:
var x = (TValue)(object)1;
If I didn't have (object), it wouldn't compile. (See this blog post by Eric Lippert for details.)
Questions
Why can you convert from a boxed int to an enum, but not to a nullable enum (and not to a long nor a long?)?
What's the easiest way to rewrite var x = (TValue)(object)1; so that it compiles, works at runtime, and is performant (assuming TValue is determined to be a Foo? at runtime)?
To answer the first question, you can convert from a boxed value to an enum only if the boxed value is of the enum's underlying type. Had you declared
enum Foo : byte { ...
you would not be able to cast from boxed int to Foo.
To answer the second question, try
var x = (TValue)Enum.ToObject(typeof(TValue), 1);
This involves boxing, though; if you need a solution that won't box, it will be more complicated.
Nullables are not some special category of atomic types, but shorthand for type Nullable<T>, which is why you can't cast a boxed int to a nullable enum. If you want to create a nullable enum, you can do it thusly:
var x = new Nullable<Foo>((Foo)1);
This answers both your questions, I think!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With