考虑以下::

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 件事::

  1. 为什么我可以拆箱 StringComparison?我想这是因为它的基础类型是 Int32 但我还是觉得很奇怪。
  2. 为什么 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 运算符中指定的类型相同。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top