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