盒装可空的底层类型可以转换为枚举,但盒装枚举类型不能转换为可空类型

naw*_*fal 5 c# enums boxing casting nullable

  • 盒装可空的底层类型可以转换为枚举,但盒装枚举类型不能转换为可空类型.

同样地,

  • 盒装可空枚举可以转换为底层类型,但盒装底层类型不能转换为可以为空的枚举.

好吧,我知道"盒装可空类型"并不是描述它的最佳方式,但这是为了问题.我知道这是基础价值类型的盒装.

我将用例子来展示它.假设我有一个enumwith int作为底层类型.

enum Sex { Male, Female }
Run Code Online (Sandbox Code Playgroud)

案例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
Run Code Online (Sandbox Code Playgroud)

案例二:

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
Run Code Online (Sandbox Code Playgroud)

简而言之,

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

(int)enum? -> succeeds
(enum?)int -> the reverse fails
Run Code Online (Sandbox Code Playgroud)

或者更简单的说法,

强制转换为非可空 - >成功转换
为可空 - >失败

现在我知道,一旦你输入了一个值类型,它就可以只回转到原始类型.但是,由于通过C#的规则,盒装int可以转换为enum和盒装enum可以转换为int和盒装intint?和盒装int?int,我一直在寻找的其他情形一致的理解,以及,即那些上面列出.但我没有得到逻辑.首先,我觉得如果它们都失败了,或者它们都成功了,那对开发者来说就更有意义了.二,即使是成功的演员也看起来有些奇怪.我的意思是因为值类型可以隐式地转换为可以为空的等价物(而不是相反的方式),所以无论如何都应该成为可以为空的强制转换,但是对于当前的实现,可以将可空类型成功转换为非可空类,甚至可以如果前者具有空值,则失败.如果整个事情已经完全相反,那将更容易理解.一个例子如:

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
Run Code Online (Sandbox Code Playgroud)

问题:

  1. 那么C#规则是如何让这种情况发生的呢?

  2. 有一种简单的方法可以记住这个吗?

Jon*_*eet 4

unbox我认为这是和IL 指令的精妙之处unbox.any

来自 ECMA 335,第 III.4.32 节(unbox操作 -unbox.any类似)

例外:如果obj不是装箱值类型、valuetype是 a且obj不是装箱值类型,或者obj中包含的值的类型不是验证器可分配给(III.1.8.2.3) valuetype
System.InvalidCastException,则抛出该异常。Nullable<T>T

例如,在这种情况下:

Sex e = Sex.Male;
object o = e;
int? i = (int?)o;
Run Code Online (Sandbox Code Playgroud)

完全正确地失败了- 因为valuetype并且objNullable<int>的值不是装箱的。“验证者可分配给”部分不适用于这种情况。intNullable<T>

不幸的是,我怀疑 C# 规范中是否描述了这种行为 - 我认为没有描述从“装箱int”到“底层类型为枚举int”的拆箱行为,据我所知,这是一个这是在混合中包含可空性的先决条件。