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

时间:2013-12-18 10:23:08

标签: c# casting enums nullable boxing

  • 盒装可空底层类型可以强制转换枚举,但盒装枚举类型无法投射为可空类型。

同样地,

  • 盒装可为空的枚举可以投射到底层类型,但是盒装底层类型无法投射到可以为空的枚举。

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

我将用例子展示它。假设我有enum int作为基础类型。

enum Sex { Male, Female }

案例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

案例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

简而言之,

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

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

或者更简单的说法,

  

施放到不可空的 - >成功
  施放到可空的 - >失败

现在我知道,一旦你输入了一个值类型,它就可以只回转到原始类型。但是,根据C#规则,可以将框int转换为enum,并将框enum转换为int,并将框int转换为int? {1}}和一个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. 我能记住一个简单的方法吗?

1 个答案:

答案 0 :(得分:4)

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

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

  

例外:
  如果 obj 不是盒装值类型,则会引发System.InvalidCastException valuetype Nullable<T> obj 不是盒装的 T ,或者 obj 中包含的值的类型不是 verifier-assignable-to (III.1.8.2.3) valuetype

例如,在这种情况下:

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

完全正确 - 因为 valuetype Nullable<int> obj 的值是不是盒装int。 “verifier-assignable-to”部分不适用于Nullable<T>个案。

我怀疑在C#规范中描述了这种行为,遗憾的是 - 我不认为从“盒装int”到“枚举基础类型为int”的拆箱行为据我所知,这是一种先决条件,包括混合中的可空性。