【问题标题】:Why can't I declare an enum inheriting from Byte but I can from byte?为什么我不能声明一个从 Byte 继承的枚举,但我可以从 byte 继承?
【发布时间】:2011-06-27 16:18:55
【问题描述】:

如果我这样声明一个枚举...

public enum MyEnum : byte {
    Val1,
    Val2
}

...它正在工作。

如果我这样声明一个枚举...

public enum MyEnum : System.Byte {
    Val1,
    Val2
}

...它不工作。编译器抛出:

错误 CS1008:需要类型 byte、sbyte、short、ushort、int、uint、long 或 ulong

由于 byte 是实际类型 System.Byte 的别名,为什么我不能使用第二个声明?

【问题讨论】:

  • 出于好奇,您是否尝试过使用 System.Int32?我知道它没有回答你的问题。我只是想知道它是否特定于字节。
  • @Mike:我很确定这不是具体的。我也遇到过这个问题(我非常喜欢旧名称的“新”名称,并尽可能尝试使用它们)。我认为他们只是没有更新解析器/编译器或其他东西(它看到 Byte 并且不承认它是 byte
  • 和@Brad Christie。谢谢,只是好奇,现在不在编译器附近。这是有道理的,如果它发生在一个人身上,它就会发生在所有人身上,但你只是想确定一下。
  • 这不再是真的。参考:stackoverflow.com/a/35571818

标签: c# compiler-errors


【解决方案1】:

最简单的答案是“这就是它指定的方式”。 (它在 C# 4 规范的第 14.1 节中。编号可能因其他版本而异。)

规范没有给出任何具体原因1,但可以说描述整数类型别名(它们都是关键字)比说它可以是任何可以解析的类型更容易(通过其他类型别名,例如 using 指令)到特定集合之一。

你有什么理由想要改用System.Byte吗?


1 带注释的 C# 4 规范在本节中确实有 one 注释......但它是我写的,只是指出这是其中之一规范中的几个地方你真的不能用普通类型名称替换别名。所以对这个问题不是很有帮助:)

【讨论】:

  • “你有什么理由想用 System.Byte 代替吗?”...实际上是的。我的团队正在开展一个项目,其中有人决定使用完整类型名称而不是别名,因为无论完整类型是否显示为类型,别名都显示为关键字。同意与否,为了保持一致,我想使用完整的类型。幸运的是,我不会因为在这里使用别名而失去工作:)
  • @Steve:Ick。你有我的遗憾。虽然很难与规范争论:)
【解决方案2】:

嗯,这是根据规范(§14.1)。语法指定enum-declaration 的产生式是

enum-declaration:
    attributes_opt   enum-modifiers_opt   enum   identifier   enum-base_opt   enum-body   ;_opt

在哪里

enum-base

:integral-type

integral-type:
sbyte
byte
short
ushort
int
uint
long
ulong
char

至于规范为什么是这样的,不清楚。

请注意,char 被列为 integral-type 的终端,但规范明确指出

请注意,char 不能用作基础类型。

顺便说一句,我真的认为这里的最佳做法是使用别名。当我想调用静态方法时,我只对这些原始类型(和string)使用 .NET 名称而不是 C# 关键字。所以

Int32.TryParse

而不是

int.TryParse.

否则,我说,例如,typeof(int) 而不是typeof(Int32)

【讨论】:

  • @Jason:有道理。为了好玩,我尝试使用 enum myenum : char,尽管您在此处发布了语法摘录,但它并没有奏效
  • 确实,规范明确指出:“请注意,char 不能用作基础类型。”
  • @Steve B,@Jon Skeet:我也注意到了;当我在对该问题的评论中进行编辑时,我们都发现了它。
  • 出于好奇,您有什么理由不将别名用于静态方法调用?我听说其他人提到他们遵循这种做法,但我不“明白”。
  • 为什么 char 会被排除在底层类型之外?
【解决方案3】:

看起来它不接受实际的类型名称,而只接受语言关键字

【讨论】:

    【解决方案4】:

    这是来自MSDN 的至少部分答案:

    每个枚举类型都有一个 基础类型,可以是任何 除 char 以外的整型。默认 枚举的基础类型 元素是int。声明一个枚举 另一种整数类型,例如字节, 在标识符后使用冒号 后跟类型,如图 下面的例子。

    Copyenum Days : byte {Sat=1, Sun, Mon, 周二、周三、周四、周五};

    批准的 枚举的类型是 byte、sbyte、 short、ushort、int、uint、long 或 乌龙。

    【讨论】:

      【解决方案5】:

      这里提出了许多问题。

      为什么我不能声明一个继承自 Byte 的枚举但我可以从 byte 继承?

      正如其他人所指出的,这就是规范所说的。

      语言设计委员会的说明并不能证明这一决定的合理性。 2000 年 6 月的笔记说


      预定义类型的关键字(例如 int)及其对应的类型名称(例如 Int32)大部分可以但不完全可以互换使用。我们讨论了是否想在这方面做出任何改变。我们没有。

      这里列出了它们不可互换的地方。

      • “int”可以用作枚举的底层类型; Int32 不能。
      • 别名声明不能使用关键字。

      我对这个主题的一些思考:

      首先想到的是,每次你给用户一个选择时,你就给了他们一个编写 bug 的机会,而每次你给他们一个编写 bug 的机会时,你都必须给出一个错误消息为了它。如果我们允许“enum X : Byte”,那么当用户意外删除“using System;”时,我们会给出一个合理的错误消息。我们可以避免这种潜在的混乱以及开发和测试错误报告启发式的所有成本,只需从一开始就不允许选择。

      想到的第二件事是枚举的底层类型基本上是关于枚举的机制,而不是它的含义。因此,底层类型子句应该限于不需要语义分析的事物似乎是合理的。我们知道底层类型是八种可能的类型之一,所以让用户从这八种类型中明确地选择一种。

      想到的第三件事是错误分析可以在句法分析而不是语义分析期间进行。越早发现错误越好。

      更新:我刚刚问了那天在房间里的一个人,我的沉思中是否有什么遗漏的地方,他说是的,他们考虑了一下,并决定进行完整的类型分析是为了开发、测试和维护团队,为用户买来的工作没有任何价值。 (他还指出,他们对 System.Void 有类似的争论;例如说“public static System.Void Main(string[] args)”是否合法?再次,他们认为这对用户没有任何价值,但确实添加潜在的歧义并为团队工作。)


      为什么“char”不是合法的底层类型?

      再一次,这就是规范所说的。同样,1999 年 10 月的语言设计说明也无助于确定原因:


      无符号整数类型可以用作枚举的基础类型。唯一不能使用的整数类型是 char。


      再次,我们可以猜测。我的猜测是枚举旨在成为花哨的数字。字符实际上是整数作为实现细节,但逻辑上它们不是数字,它们是字符。我们希望能够对枚举进行操作,例如加法、“or-ing”和“and-ing”标志等等;规范很清楚,这些操作就像在基础类型上完成一样完成。 char 类型在逻辑上不是数字,并没有定义您可能需要的所有运算符。最后,如果您想要一个两字节的枚举值,那么您已经可以使用 short 和 ushort。


      一封电子邮件中关于此问题的相关问题:

      仔细阅读语法规范说'char'在语法上是一个合法的底层类型,但是语法后面的解释性文本段落说'char'不是一个合法的底层类型。规格不一致吗?

      是的。我不会因此而失眠。如果它让你感觉更好,想象一下语法行说

      enum-base : integral-type

      改为读取

      enum-base : integral-type(但不是char

      【讨论】:

        【解决方案6】:

        仅供参考:

        使用新的编译器 Roslyn 这个代码

        enum SomeEnum : System.Int32
        {
            None,
            Some
        }
        

        是有效的,所以,现在枚举基类型不仅可以使用别名,还可以使用完整类型。

        dotnetfiddle 上的示例,您可以在其中选择编译器:https://dotnetfiddle.net/oXyAgV

        【讨论】:

        • 今天这应该是答案:)
        猜你喜欢
        • 2016-05-16
        • 2023-02-24
        • 1970-01-01
        • 2010-09-28
        • 1970-01-01
        • 2010-10-19
        相关资源
        最近更新 更多