【问题标题】:X is enum - is this according to spec?X 是枚举 - 这是根据规范吗?
【发布时间】:2012-02-07 13:37:38
【问题描述】:

Test if an object is an Enum 讨论使用is Enum 测试对象以查看它是否包含枚举值。

这是在规范中的任何地方指定的吗? is(版本 4.0 中的 7.10.10)上的条目列出了以下可能的右手值:

  • 匿名函数
  • 方法组
  • 引用类型**这可能是一个枚举?
  • 可空类型
  • 不可为空的值类型**这可能是一个枚举?

假设枚举值与上面列表中的“引用类型”匹配 - 规范声明如下:

...如果 D [RHS 的动态类型)] 和 T [LHS] 是相同类型,如果 D 是引用类型并且存在从 D 到 T 的隐式引用转换,则结果为真,或者如果 D 是值类型并且存在从 D 到 T 的装箱转换。

is Enum 的情况下,这些条件是否严格正确?没有编译器支持,例如 is classis struct

那么对is Enum的支持是按照规范,还是实现决策?

【问题讨论】:

  • 是什么让你认为枚举 valuereference 类型?
  • @BoltClock:因为代码是这样说的! typeof(Enum).IsValueType => false
  • 您是专门询问Enum 类型还是用户定义的枚举?似乎有点混乱(包括我;p)
  • 您如何拥有Enum 的实例?它或多或少是一个抽象类。

标签: c# enums language-implementation


【解决方案1】:

不支持is classis struct,因为没有可以区分类或结构与其他类型的通用基类型。 is Enum 有效,因为 System.Enum 是一个实际类型,它是所有枚举的基础。而Enum 是引用类型,所以最后一部分适用:

如果 D 是值类型并且存在从 D 到 T 的装箱转换

D(左侧表达式的类型)是值类型。而TEnum,它是D 的基本类型。所以有一个从DEnum的装箱转换,所以表达式的值为true

从任何枚举到Enum 的装箱转换在§14.4 System.Enum 类型中明确指定:

System.Enum 类型是所有枚举类型的抽象基类(这与枚举类型的底层类型不同且不同),从System.Enum 继承的成员可用于任何枚举类型。从任何枚举类型到System.Enum 都存在装箱转换,从System.Enum 到任何枚举类型都存在拆箱转换。

注意System.Enum 本身并不是一个枚举类型。相反,它是一个 class-type,所有 enum-type 都从该 enum-type 派生而来。 System.Enum 类型继承自 System.ValueType 类型,而 System.ValueType 又继承自 object 类型。在运行时,System.Enum 类型的值可以为 null 或对任何枚举类型的装箱值的引用。

【讨论】:

    【解决方案2】:

    Enum 是一个引用类型。

    typeof(Enum).IsValueType => false
    

    有趣的是,

    typeof(ValueType).IsValueType => false
    

    【讨论】:

    【解决方案3】:

    Enum 是一种实际类型,而 class 和 struct 不是。因此,Enum 可以用在 class 和 struct 不能用的右侧。

    【讨论】:

    • 不完全。你只是自相矛盾:)
    • 有趣……嗯,嗯……埃里克·利珀特在哪里……也许​​他可以回答这个问题……
    • @leppie,没有矛盾。 System.Enum 是一个实际类型。类或结构没有这种类型。有System.ValueType,但这是所有值类型的基础,而不仅仅是结构。
    【解决方案4】:

    这里问的是什么对我来说并不完全清楚,但我希望我现在明白了。


    给定下面的代码:

    void F(Object obj) {
      var isEnum obj is Enum;
      ...
    }
    

    obj 是枚举类型的实例时,C# 标准的哪些部分规定isEnum 为真?


    14.9.10 is operatorC# Language Specification 中有五个项目符号描述了它是如何评估的:

    • 第一个项目符号是关于obj 的类型比System.Object 更具体的情况。

    • 第二个要点是关于可空类型。

    • 第四条是关于泛型的。

    • 第 5 个项目符号是当没有匹配项并且 is 运算符评估为 false 时,我们知道它不会。

    您会认为第三个项目符号适用于上面的代码。第 3 个项目符号有四个子项目符号:

    • obj 为空时适用第一个子项目符号。

    • 第二个子项目符号是关于可空类型的。

    • 第 4 个子项目符号是当没有匹配项且 is 运算符评估为 false 时,我们知道它不会。

    您会期望第三个子项目符号适用:

    否则,令 R 为 e 引用的实例的运行时类型。如果 R 和 T 是同一类型,如果 R 是引用类型并且存在从 R 到 T 的隐式引用转换,或者如果 R 是值类型 而T是R实现的接口类型,结果为真。

    但是,这里似乎缺少一些关于枚举类型的特定内容。假设obj 是枚举类型MyEnum 的实例,没有一个子句与上面的代码匹配:

    • R 和 T 不是同一类型,因为 R 是 MyEnum 而 T 是 System.Enum

    • R 是 MyEnum,它是值类型 (11.1.9) 而不是引用类型。

    • T 是System.Enum,不是接口类型。

    我不想声称规范中存在错误,但是在详细阅读 14.9.10 之后,我无法看到is Enum 如何评估为 true 给定对枚举类型的盒装引用.

    知道标准的人通常比我聪明得多,我可能忽略了一些东西,但即使我没有这不应该阻止你使用is Enum 来测试一个类型是否是一个枚举。我敢肯定,它不是可以这样使用的实现细节。

    【讨论】:

    • @leppie:您的断言是正确的,但我不是在谈论Enum 类型。我说的是枚举,typeof(MyEnumeration).IsValueTypetrue 用于您通过关键字 enum 定义的任何 MyEnumeration
    • 但问题是关于Enum,而不是MyEnum。我读错问题了吗?
    • 我把这个问题读作“规范中的什么地方解释了为什么 X is Enum == trueX 是一个枚举?”
    • 我不否认可以将枚举值强制转换为 Enum - 我在问您从规范中引用的段落之后的项目符号列表如何涵盖这种情况。同样,我看不出它如何涵盖3 is object 的案例。
    • 在您使用的规范的 ECMA 版本中,第一个项目符号适用:存在从任何枚举类型到 Enum 的装箱转换。
    猜你喜欢
    • 2014-08-06
    • 1970-01-01
    • 2012-08-07
    • 2022-07-13
    • 2020-07-06
    • 2014-07-06
    • 1970-01-01
    • 2012-09-14
    • 2020-10-27
    相关资源
    最近更新 更多