题
考虑以下::
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
, ,那么为什么对于可为 null 的值不成立呢?同样,如果我装箱而不是 5 StringComparison.OrdinalIgnoreCase
, ,那就是 nullableInt
将为空,但是 nullableEnum
不会是。
解决方案
严格来说我认为这是一个 错误地 的实施细节 运行时,因为 C# 规范说
如果源操作数为 null,则拆箱到可为 null 类型会生成可为 null 类型的 null 值,否则会生成将对象实例拆箱为可为 null 类型的基础类型的包装结果。
也就是说,如果拆箱到 StringComparison 有效,那么拆箱到 Nullable<StringComparison> 也应该有效。目前尚不清楚两者是否都应该有效或者都应该失败。规范说
为了在运行时成功进行到给定非空值类型的拆箱转换,源操作数的值必须是对该非空值类型的装箱值的引用。
您必须确定装箱 int 是否被视为 StringComparison 类型的装箱值,因为 StringComparison 的基础类型是 int。规范还指出,如果盒子包含“不兼容的对象”,则会抛出 InvalidCastException。int 当然与 StringComparison“兼容”,因为您可以安全地将四个字节从堆复制到 StringComparison 变量中。
其他提示
当您将枚举或整数转换为对象时,它仍然保留类型信息。所以 box is StringComparison
将返回 false
. 。但允许将任何 enum 或 int 强制转换为任何 enum,因此显式强制转换 (StringComparison)box
作品。这是枚举的特例。 Nullable<T>
, 另一方面,它只是一个普通的类,当您转换或检查类型时,T 不会以任何特定方式处理。这就是为什么这段代码会抛出异常。
StringComparison? nullableEnum = (StringComparison?)nullableInt;
1)是的,枚举的基础类型是 int,这就是它以这种方式工作的原因。更。您可以执行以下操作:
enum MyEnum { One = 1, Two = 2, } int i = 3; MyEnum myEnum = (MyEnum)i; // This works without exceptions.
2)因为 StringComparison?
实际上是 Nullable<StringComparison>
这是不同的类型。和 as
运算符仅检查对象是否与 as 运算符中指定的类型相同。