可空盒装基础类型可以转换为枚举,但盒装枚举类型不能转换为可空类型 [英] Boxed nullable underlying type can be cast to enum but boxed enum type can't be cast to nullable type
问题描述
- 盒装为空的基础类型的可投以枚举,但盒装枚举类型的不能转换可空类型。
同样,
- 盒装为空的枚举的可投以基本类型,但是盒装的基础类型的不能转换以可空的枚举。
的好吧,我知道盒装可空类型是不是来形容它的最好方式,但它的问题的缘故。我知道那就是变得越来越盒装基础值类型。的
我将举例证明这一点。假设我有一个枚举
与 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; //无效的转换,尽管它始终是一个安全的投
问题:
那么,C#规则是让这种情况发生?
有一个简单的方法我记得这个吗?
解决方案我觉得这是对一个微妙
拆箱
和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
withint
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 -> failsNow 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 toenum
and a boxedenum
can be cast toint
, and a boxedint
toint?
and a boxedint?
toint
, 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:
So what C# rule is letting this happen?
Is there a simple way I can remember this?
解决方案I think this is a subtlety of the
unbox
andunbox.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 aNullable<T>
and obj is not a boxedT
, 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 boxedint
. The "verifier-assignable-to" part doesn't apply for theNullable<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 ofint
" is described, as far as I can see, which is a sort of prerequisite to then including nullability in the mix.这篇关于可空盒装基础类型可以转换为枚举,但盒装枚举类型不能转换为可空类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!