可空盒装基础类型可以转换为枚举,但盒装枚举类型不能转换为可空类型 [英] Boxed nullable underlying type can be cast to enum but boxed enum type can't be cast to nullable type

查看:159
本文介绍了可空盒装基础类型可以转换为枚举,但盒装枚举类型不能转换为可空类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


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



同样,




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



好吧,我知道盒装可空类型是不是来形容它的最好方式,但它的问题的缘故。我知道那就是变得越来越盒装基础值类型。



我将举例证明这一点。假设我有一个枚举 INT 作为基础类型。

 枚举性别{男,女} 

案例一

 诠释? I = 1; 
对象o = I;
性别E =(性别)O; //成功

//但是

性别E = Sex.Male;
对象o = E;
诠释? I =(INT)O; //无效转换



案例二:

 性爱? E = Sex.Male; 
对象o = E;
INT I =(INT)O; //成功

//但是

INT I = 1;
对象o = I;
性别? E =(性别)O; //无效转换



简而言之,



 (枚举)INT? - >成功
(INT?)枚举 - >反向失败

(INT)枚举? - >成功
(枚举?)INT - >反向失败

或在更简单来说,




转换为不可为空 - >成功结果
投可空 - >失败




现在我知道,一旦你框中输入一个值类型,它可以转换回来才原始类型。但由于采用C#的规则,一个盒装 INT 可强制转换为枚举和盒装枚举可强制转换为 INT 和盒装 INT 诠释?和盒装 INT? INT 后,我一直在寻找对于其他情况一致的理解以及,即上面列出的。但我不明白的逻辑。 其一,我觉得,如果这些都失败了,或者如果他们都成功了,它的开发人员更有意义。 二,即使是成功的演员看起来有些奇怪。我的意思是因为值类型可以被隐式转换为它的可空当量(而不是相反的方式),强制转换为可空无论如何都应该成功,但与目前的实施可空类型被成功地转换为不可为空这甚至可以如果前者有一个空值失败。已经反过来这件事,那本来就容易理解。

 性别:像一个例子吗? E = NULL; 
对象o = E;
INT I =(INT)O; //成功,但一定要对爆炸投

//但是

INT I = 1;
对象o = I;
性别? E =(性别)O; //无效的转换,尽管它始终是一个安全的投



问题:




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


  2. 有一个简单的方法我记得这个吗?



解决方案

我觉得这是对一个微妙拆箱 unbox.any IL指令。



从ECMA 335,部分III.4.32(拆箱运行 - unbox.any 相似)




例外:结果
System.InvalidCastException 被抛出,如果的 OBJ 不是装箱的值类型,的值类型的是 可空< T> 的和的 OBJ 不是盒装的 T 的,或者如果包含在值的类型的 OBJ 的不是的验证-assignable到的(III.1.8.2.3)的值类型




因此,例如,在这种情况下:

 性爱E = Sex.Male; 
对象o = E;
诠释? I =(INT)O;



失败的完全正确的 - 因为的值类型的在可空< INT> 和值的 OBJ 的是的的盒装 INT 。 校验可分配到部分不适用的可空< T> 情况



我毋庸置疑,任何这种行为在C#规范中描述,遗憾的是 - 我不认为从盒装 INT 拆箱行为枚举具有基础类型的 INT 的描述,据我所看到的,这是一种先决条件,以然后包括在混合为空。


  • Boxed nullable underlying type can be cast to enum but boxed enum type can't be cast to nullable type.

And similarly,

  • Boxed nullable enum can be cast to underlying type but boxed underlying type can't be cast to nullable enum.

Ok, I know "boxed nullable type" is not the best way to describe it, but it's for the sake of the question. I'm aware it's the underlying value type that's getting boxed.

I will show it with examples. Assume I have an enum with int as the underlying 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,

cast to non-nullable -> succeeds
cast to nullable -> fails

Now I do know that once you box a value type, it can be cast back only to the original type. But since by C# rules, a boxed int can be cast to enum and a boxed enum can be cast to int, and a boxed int to int? and a boxed int? to int, I was looking for a consistent understanding of other scenarios as well, ie the ones listed above. But I dont get the logic. For one, I feel if they all failed or if they all succeeded, it made more sense to developers. Two, even the successful casts look a little odd. I mean since a value type can be implicitly cast to its nullable equivalent (and not the other way around), a cast to nullable should anyway succeed, but with the current implementation a nullable type is being successfully cast to non-nullable which can even fail if the former had a null value. Had this whole thing been other way around, it would have been easier comprehending. An example like:

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:

  1. So what C# rule is letting this happen?

  2. Is there a simple way I can remember this?

解决方案

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

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

Exceptions:
System.InvalidCastException is thrown if obj is not a boxed value type, valuetype is a Nullable<T> and obj is not a boxed T, or if the type of the value contained in obj is not verifier-assignable-to (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 entirely correctly - because valuetype is Nullable<int> and the value of obj is not a boxed int. The "verifier-assignable-to" part doesn't apply for the Nullable<T> case.

I doubt that any of this behaviour is described in the C# specification, unfortunately - I don't think the unboxing behaviour from "boxed int" to "enum with an underlying type of int" is described, as far as I can see, which is a sort of prerequisite to then including nullability in the mix.

这篇关于可空盒装基础类型可以转换为枚举,但盒装枚举类型不能转换为可空类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆