盒装可为空的基础类型可以强制转换为枚举,但盒装枚举类型不能强制转换为可为空的类型

本文关键字:类型 转换 枚举 盒装 不能 | 更新日期: 2024-10-24 21:47:14

    盒装可为空的基础类型可以强制转换为
  • 枚举,但盒装枚举类型不能强制转换为可为空的类型。

同样,

    盒装可空枚举可以强制转换为基础类型
  • ,但盒装基础类型不能强制转换为可为空的枚举。

好的,我知道"盒装可为空类型"不是描述它的最佳方式,但这是为了这个问题。我知道这是被框住的基础值类型。

我将用例子来展示它。假设我有一个enumint 作为基础类型。

enum Sex { Male, Female }

案例一:

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

案例二:

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

简而言之

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

或者更简单的话,

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

现在我确实知道,一旦你对值类型进行框箱,它只能被强制转换为原始类型。但是由于根据 C# 规则,盒装int可以强制转换为enum,盒装enum可以强制转换为int,盒装int可以强制int?,盒装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

问题:

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

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

盒装可为空的基础类型可以强制转换为枚举,但盒装枚举类型不能强制转换为可为空的类型

我认为这是 IL 指令unboxunbox.any的微妙之处。

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

异常:
如果 obj 不是装箱值类型,值类型是Nullable<T>,而 obj 不是装箱T,或者 obj 中包含的值的类型不是可分配给 (III.1.8.2.3值类型的验证程序,则会抛出System.InvalidCastException

例如,在这种情况下:

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

完全正确失败 - 因为 valuetypeNullable<int> 并且 obj 的值不是盒装int 。"验证程序可分配给"部分不适用于Nullable<T>情况。

不幸的是,我怀疑 C# 规范中是否描述了任何这种行为 - 据我所知,我不认为从"盒装int"到"具有底层int类型的枚举"的开箱行为被描述,这是在组合中包含可空性的一种先决条件。