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

时间:2011-02-15 15:06:07

标签: c# compiler-errors

如果我宣布这样的枚举......

public enum MyEnum : byte {
    Val1,
    Val2
}

......它正在发挥作用。

如果我宣布这样的枚举......

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

......它不起作用。编译器抛出:

  

错误CS1008:输入byte,sbyte,short,ushort,int,uint,long或ulong expected

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

6 个答案:

答案 0 :(得分:29)

这里提出了一些问题。

  

为什么我不能声明从字节继承的枚举,但我可以从字节?

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

语言设计委员会注意到这一决定并不合理。 2000年6月的笔记说


  

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

     

以下是不可互换的地方列表。

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

关于这个问题我的一些想法:

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

首先想到的是,枚举的基础类型基本上是关于枚举的机制,而不是含义。因此,似乎有理由认为,基础类型条款应限于不需要语义分析的事物;我们知道底层类型是八种可能的类型之一,所以让我们让用户机械地从这八种类型中的一种中明确地选择。

首先想到的是错误分析可以在句法分析过程中进行,而不是语义分析。错误越早发现越好。

更新:我刚问那天在房间里的一个人是否在我的思考中遗漏了什么,他说是的,他们想到了并决定做全类型分析是为了开发,测试和维护团队,购买用户没有任何价值的工作。 (他还注意到他们在System.Void上有类似的论点;例如,说“public static System.Void Main(string [] args)”是否合法?再次,他们认为这对用户没有增加任何价值但是增加潜在的模糊性并为团队工作。)


  

为什么“char”不是合法的基础类型?

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


  

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


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


有关此问题的电子邮件中的相关问题:

  

仔细阅读语法规范说'char'在语法上是一种合法的基础类型,但语法后的解释性文本段落说'char'不是合法的基础类型。规格是否不一致?

是。我不会因此失眠。如果它让你感觉更好,想象一下

的语法行

enum-base 整数类型

而是读取

enum-base 整数类型(但不是char

答案 1 :(得分:26)

嗯,这是根据规范(§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)

答案 2 :(得分:10)

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

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

想要使用System.Byte是否有任何理由?


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

答案 3 :(得分:2)

以下是答案,至少部分来自MSDN

  

每个枚举类型都有一个   基础类型,可以是任何类型   整数类型除了char。默认   基础类型的枚举   元素是int。宣布一个枚举   另一种整数类型,如byte,   在标识符后面使用冒号   其次是类型,如图所示   以下示例。

     

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

     

批准   枚举的类型是byte,sbyte,   简而言之,ushort,int,uint,long或   ULONG。

答案 4 :(得分:2)

仅供参考:

使用新编译器Roslyn此代码

enum SomeEnum : System.Int32
{
    None,
    Some
}

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

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

答案 5 :(得分:1)

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