代码之家  ›  专栏  ›  技术社区  ›  Michael B

为什么取消装箱枚举会产生奇怪的结果?

  •  6
  • Michael B  · 技术社区  · 15 年前

    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.
    

    两件事:

    1. 为什么我能解开 StringComparison Int32 但我还是觉得很奇怪。
    2. nullableEnum 值为空?

    int 可以取消绑定到 Enum StringComparison.OrdinalIgnoreCase ,那就是 nullableInt 将为空,但是 不会的。

    3 回复  |  直到 15 年前
        1
  •  3
  •   stevemegson    15 年前

    严格地说,我认为这是 窃听 实施细节 运行时,因为C规范说

    如果源操作数为空,则取消对可为空类型的装箱将生成可为空类型的空值,否则将对象实例取消对可为空类型的基础类型的装箱结果。

    若要在运行时成功取消对给定不可为空值类型的转换的装箱,源操作数的值必须是对该不可为空值类型的装箱值的引用。

    必须确定装箱的int是否被视为StringComparison类型的装箱值,因为StringComparison的基础类型是int。规范接着指出,如果该框包含“不兼容对象”,则抛出InvalidCastException。int当然与StringComparison“兼容”,因为您可以安全地将堆中的四个字节复制到StringComparison变量中。

        2
  •  1
  •   Athari    15 年前

    将枚举或整数强制转换为对象时,它仍保留类型信息。所以 box is StringComparison false . 但是允许将任何枚举或int强制转换为任何枚举,因此显式强制转换 (StringComparison)box 作品。这是枚举的特例。 Nullable<T> 另一方面,它只是一个普通的类,当您转换或检查类型时,不会以任何特定的方式处理T。这就是此代码将引发异常的原因。

            StringComparison? nullableEnum = (StringComparison?)nullableInt;
    
        3
  •  -1
  •   Andrew Bezzub    15 年前

    enum MyEnum
    {
        One = 1,
        Two = 2,
    }
    
    int i = 3;
    MyEnum myEnum = (MyEnum)i; // This works without exceptions.
    

    2) 因为 StringComparison? 实际上是 Nullable<StringComparison> as operator只检查对象是否与as operator中指定的类型相同。

    推荐文章