考虑以下内容:
Object box = 5;
int @int = (int)box; // int = 5
int? nullableInt = box as int?; // nullableInt = 5;
StringComparison @enum = (StringComparison)box; // enum = OrdinalIgnoreCase
StringComparison? nullableEnum = box as StringComparison?; // nullableEnum = null.
2件事::
StringComparison
?我想这是因为它的基础类型是Int32
,但我仍然觉得它很奇怪。nullableEnum
的值为null?据我所知,唯一有效的拆箱是从盒装值类型到它的类型或可空类型。如果int
可以取消装箱到Enum
,那么为什么不能对可空值进行同样的操作?同样,如果我将StringComparison.OrdinalIgnoreCase
设为nullableInt
,而nullableEnum
将为空,而不是{{1}}。
答案 0 :(得分:2)
严格来说,我认为这是运行时 实现细节中的错误,因为C#规范说
如果源操作数为null,则取消装入nullable-type会产生nullable-type的null值,否则会将对象实例的解包装结果解析为nullable-type的基础类型。
也就是说,如果取消装配到StringComparison,则取消装箱到Nullable< StringComparison>也应该工作。有两点是否应该有效或两者都失败有点不清楚。规范说
对于在给定的非可空值类型的取消装箱转换以在运行时成功,源操作数的值必须是对该非可空值类型的装箱值的引用。
您必须确定boxed int是否被认为是StringComparison类型的盒装值,因为StringComparison的基础类型是int。规范继续说如果该框包含“不兼容的对象”,则抛出InvalidCastException。 int当然与StringComparison“兼容”,因为您可以安全地将堆中的四个字节复制到StringComparison变量中。
答案 1 :(得分:1)
当您将enum或integer强制转换为object时,它仍然保存类型信息。因此box is StringComparison
将返回false
。但允许将任何枚举或int转换为任何枚举,因此显式转换(StringComparison)box
有效。这是枚举的特例。另一方面,Nullable<T>
只是一个普通的类,当你强制转换或检查类型时,T不会以任何特定的方式处理。这就是为什么这段代码会抛出异常。
StringComparison? nullableEnum = (StringComparison?)nullableInt;
答案 2 :(得分:-1)
1)是的,枚举的基础类型是int,这就是它以这种方式工作的原因。更。你可以这样做:
enum MyEnum { One = 1, Two = 2, } int i = 3; MyEnum myEnum = (MyEnum)i; // This works without exceptions.
2)因为StringComparison?
实际上是Nullable<StringComparison>
,它是不同的类型。 as
运算符仅检查对象是否与运算符中指定的类型相同。