7

考虑以下::

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,那么为什么对于可空值不适用呢?同样,如果不是 5 I boxed StringComparison.OrdinalIgnoreCase,那nullableInt将是 null,但nullableEnum不会。

4

3 回答 3

3

严格来说我认为这是一个错误 运行时的实现细节,因为 C# 规范说

如果源操作数为 null,则对可空类型拆箱产生可空类型的空值,否则将对象实例拆箱到可空类型的基础类型的包装结果。

也就是说,如果取消装箱到 StringComparison 有效,那么取消装箱到 Nullable<StringComparison> 也应该有效。两者都应该工作还是都应该失败,这有点不清楚。规范说

为了在运行时成功地对给定的非可空值类型进行拆箱转换,源操作数的值必须是对该非可空值类型的装箱值的引用。

您必须决定是否将装箱的 int 视为 StringComparison 类型的装箱值,因为 StringComparison 的基础类型是 int。规范继续说,如果盒子包含“不兼容的对象”,则会引发 InvalidCastException。int 肯定与 StringComparison “兼容”,因为您可以安全地将堆中的四个字节复制到您的 StringComparison 变量中。

于 2010-10-26T18:43:41.073 回答
1

当您将枚举或整数转换为对象时,它仍然保存类型信息。所以box is StringComparison会回来false。但是允许将任何 enum 或 int 强制转换为任何 enum,因此显式强制转换(StringComparison)box有效。这是枚举的一个特例。Nullable<T>另一方面,它只是一个普通的类,当您转换或检查类型时,不会以任何特定方式处理 T 。这就是为什么这段代码会抛出异常。

        StringComparison? nullableEnum = (StringComparison?)nullableInt;
于 2010-10-26T18:02:40.563 回答
-1

1)是的,枚举的基础类型是 int ,这就是它以这种方式工作的原因。更。您可以执行以下操作:

enum MyEnum
{
    One = 1,
    Two = 2,
}

int i = 3;
MyEnum myEnum = (MyEnum)i; // This works without exceptions.

2)因为StringComparison?实际上Nullable<StringComparison>是不同的类型。Andas运算符仅检查对象是否与 as 运算符中指定的类型相同。

于 2010-10-26T17:49:06.687 回答