A numbered numbered base type can be converted to enum, but an enum boxed type cannot be converted to NULL

  • A nested base type may be different for an enumeration, but an enumerated type cannot be added to a NULL type.

And similarly,

  • An insert with a null enum value can be dropped to the base type, but the type embedded in the kernel cannot be distinguished to a null enumeration.

Well, I know that “type with a zero number in a box” is not the best way to describe it, but it is in the name of the question. I know that this is the basic type of value that appears in the box.

I will show it with examples. Suppose I have an enum with int as the base type.

 enum Sex { Male, Female } 

Case I:

 int? i = 1; object o = i; Sex e = (Sex)o; //success //but Sex e = Sex.Male; object o = e; int? i = (int?)o; //invalid cast 

Case II:

 Sex? e = Sex.Male; object o = e; int i = (int)o; //success //but int i = 1; object o = i; Sex? e = (Sex?)o; //invalid cast 

In a nutshell

 (enum)int? -> succeeds (int?)enum -> the reverse fails (int)enum? -> succeeds (enum?)int -> the reverse fails 

Or in even simpler terms

discarded to non-nullable -> successfully cast to nullable -> fail

Now I know that once you enter a value type, it can only be dropped to the original type. But since, according to C # rules, an int can be added to an int box, and an int can be added to an enum box and from an int to an int? box int? and in the box int? before int , I was looking for a consistent understanding of other scenarios, i.e. the ones listed above. But I do not understand the logic. For one, I feel that if they all failed or they all succeeded, it made sense to the developers. Two, even successful throws, look a little strange. I mean, since the type of a value can be implicitly passed into its equivalent with a null value (and not vice versa), casting to a nullable value should succeed in any case, but with the current implementation, a type with a null value is successfully transferred to a value, not nullable, which can even if the first is null. If it were all the other way around, it would be easier to understand. Example:

 Sex? e = null; object o = e; int i = (int)o; //succeeds, but sure to explode on cast //but int i = 1; object o = i; Sex? e = (Sex?)o; //invalid cast, even though its always a safe cast 

Questions:

  • So which C # rule allows this?

  • Is there an easy way to remember this?

+5
enums casting c # nullable boxing
source share
1 answer

I think this is the subtlety of the unbox and unbox.any IL instructions.

From ECMA 335, section III.4.32 ( unbox operation - unbox.any similar)

Exceptions:
System.InvalidCastException is thrown if obj is not a boxed type, valuetype is Nullable<T> , and obj is not boxed in T , or if the type of the value contained in obj cannot be assigned to the verifier (III. 1.8.2.3 ) valuetype.

So, for example, in this case:

 Sex e = Sex.Male; object o = e; int? i = (int?)o; 

it fails completely because valuetype is Nullable<int> and obj is not an int box. The verifier-assignable-to part does not apply to the Nullable<T> case.

I doubt that any of this behavior is described in the C # specification, unfortunately - I do not think that the unboxing behavior from "boxed int " to "enum with the base type int described, since as far as I can see, that is kind a prerequisite for including the nullability value in the set.

+4
source share

All Articles