为什么我不能声明从字节inheritance的枚举但我可以从字节?
如果我宣布这样的枚举……
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
,为什么我不能使用第二个声明?
嗯,这是根据规范(§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
不能用作基础类型。
顺便说一下,我认为这里的最佳实践是使用别名。 当我想调用静态方法时,我只使用.NET名称而不是C#关键字来表示这些基本类型(和string
)。 所以
Int32.TryParse
代替
int.TryParse.
否则,我说,例如, typeof(int)
而不是typeof(Int32)
。
这里提出了一些问题。
为什么我不能声明从字节inheritance的枚举但我可以从字节?
正如其他人所指出的那样,这就是规范所说的。
语言设计委员会注意到这一决定并不合理。 2000年6月的笔记说
预定义类型(例如,int)的关键字及其对应的类型名称(例如,Int32)可以大部分但不完全可互换地使用。 我们讨论了是否要在这方面做出任何改变。 我们没有。
以下是不可互换的地方列表。
- “int”可以用作枚举的基础类型; Int32不能。
- 别名声明不能使用关键字。
关于这个问题我的一些想法:
首先想到的是,每次你给用户一个选择时,你就给他们一个写bug的机会,每当你给他们一个写bug的机会时你就必须为它做一个错误信息。 如果我们允许“枚举X:字节”,那么当用户意外删除“使用系统”时,我们会给出合理的错误消息。 我们可以避免这种潜在的混淆以及开发和测试错误报告启发式的所有成本,只是不允许首先进行选择。
我想到的第二件事是,枚举的基本类型基本上是关于枚举的机制 ,而不是它的含义 。 因此,基础类型条款应限于不需要语义分析的事物似乎是合理的; 我们知道底层类型是八种可能的类型之一,所以让我们让用户机械地从这八种类型中的一种中明确地选择。
我想到的第三件事是错误分析可以在句法分析而不是语义分析中执行。 错误越早发现越好。
更新:我刚问那天在房间里的一个人是否在我的思考中遗漏了什么,他说是的,他们想到了,并决定做完全型分析是为了开发,测试和维护团队,购买用户没有任何价值的工作。 (他还注意到他们在System.Void上有类似的论点;例如,说“public static System.Void Main(string [] args)”是否合法?再次,他们认为这对用户没有增加任何价值但是增加潜在的模糊性并为团队工作。)
为什么“char”不是合法的基础类型?
再次,这就是规范所说的。 同样,1999年10月的语言设计说明无助于确定原因:
无符号整数类型可以用作枚举的基础类型。 唯一不能使用的整数类型是char。
我们再一次猜测。 我的猜测是,枚举是为了花哨的数字。 Chars实际上是整数作为实现细节,但从逻辑上讲它们不是数字 ,而是字符 。 我们希望能够对枚举进行操作,如添加,“或”和“和”标志,等等; 规范很清楚,这些操作就像在底层类型上完成一样。 char类型(逻辑上不是数字)不会定义您可能需要的所有运算符。 最后,如果你想要一个两字节的枚举值,那么你已经拥有了short和ushort。
有关此问题的电子邮件中的相关问题:
仔细阅读语法规范说’char’在语法上是一种合法的基础类型,但语法后的解释性文本段落说’char’不是合法的基础类型。 规格是否不一致?
是。 我不会因此失眠。 如果它让你感觉更好,想象一下语法行
枚举 : 整数型
而是阅读
enum-base : 整数类型 (但不是char
)
最简单的答案是“这就是它指定的方式。” (这是在C#4规范的第14.1节中。其他版本的编号可能会有所不同。)
规范没有给出这个1的任何特定原因,但是可以说更容易描述整数类型别名(它们都是关键字),而不是说它可以是任何解析的类型(通过其他类型别名,例如using
指令)到一个特定的一组。
你有什么理由想要使用System.Byte
吗?
1带注释的C#4规范在本节中确实有一个注释……但它是由我编写的,并且只是指出这是规范中为数不多的地方之一,你实际上无法用普通类型替换别名名。 所以对这个问题不是很有帮助:)
以下是MSDN的答案,至少部分来自:
每个枚举类型都有一个底层类型,除了char之外,它可以是任何整数类型。 枚举元素的默认基础类型是int。 要声明另一个整数类型的枚举,例如byte,请在标识符后跟类型后使用冒号,如下例所示。
Copyenum Days:byte {Sat = 1,Sun,Mon,Tue,Wed,Thu,Fri};
枚举的已批准类型是byte,sbyte,short,ushort,int,uint,long或ulong。
仅供参考:
用新编译器Roslyn这段代码
enum SomeEnum : System.Int32 { None, Some }
因此,现在对于枚举基类型不仅可以使用别名,还可以使用完整类型。
可以在dotnetfiddle上选择编译器: https ://dotnetfiddle.net/oXyAgV
看起来它不接受实际的类型名称,只接受语言关键字 。