为什么这个枚举声明现在有效?
在回答另一个问题时,Jon Skeet提到enums
的定义有一个奇怪的事情。 他的回答。
他声明重新定义enum
的基础类型只能使用类型别名而不能使用框架类型( int
有效, Int32
不能等)
public enum Foo : UInt32 {} // Invalid public enum Bar : uint {} // Valid
现在我试图重现(在VS2015中使用C#6 / Roslyn),我没有得出相同的结论:
public enum TestEnum : UInt32 { }
和
public enum MyEnum : uint { }
都是完全有效的。 为什么会这样? 或者改变了什么?
编辑:
所以为了清理事情,它是C#6的一个变化,尚未被记录,并且很快就会记录下来,因为你可以从Roslyn Github上的这个git问题中读到
现在使用C#6这当然很奇怪。当前正在进行的规范仍然列出了以下用于在枚举声明中指定基类的语法:
enum_base : ':' integral_type ;
整数类型定义为实际固定标记 :
integral_type : 'sbyte' | 'byte' | 'short' | 'ushort' | 'int' | 'uint' | 'long' | 'ulong' | 'char' ;
根据此语言规范判断,解析器应拒绝使用未出现在静态类型标识符列表中的某些其他基本类型,并导致语法错误。
鉴于这不是发生的事情,有两种可能性:要么故意更改解析器以接受那里的非别名类型,要么解析器错误地接受这些。
如果我们看一下Roslyn的实现,那么我们就可以看到为什么规范中的这个要求没有得到强制执行。 枚举声明解析器根本不检查它,但解析任何类型:
BaseListSyntax baseList = null; if (this.CurrentToken.Kind == SyntaxKind.ColonToken) { var colon = this.EatToken(SyntaxKind.ColonToken); var type = this.ParseType(false); var tmpList = _pool.AllocateSeparated(); tmpList.Add(_syntaxFactory.SimpleBaseType(type)); baseList = _syntaxFactory.BaseList(colon, tmpList); _pool.Free(tmpList); }
此时,它与“正常”inheritance的代码并没有太大差别。 因此,任何类型限制都不适用于语法级别,而是适用于语义级别 – 此时可能已经评估了类型别名。
所以这似乎是一个错误:无论是在规范中还是在解析器中。 鉴于规范仍在进行中,这可能会在以后修复。
要么它是新编译器的疏忽,要么他们决定不再在语言中出现这种不一致(?)。
目前似乎没有官方规范,只有一个看起来不那么官方的git存储库,正在进行工作:
https://github.com/ljw1004/csharpspec/blob/gh-pages/enums.md
目前看起来没有使用底层枚举类型的别名应该是一个错误。 该语言看起来与之前的官方规范相同。 但由于编译器和规范似乎仍在进行中,因此很难说哪一个是正确的。
这是C#6中的故意语言更改,其规范仅以草稿forms发布。 这是一个很小的变化,我们一直忘记把它放到规格中。
另见https://github.com/dotnet/roslyn/issues/623