为什么这个枚举声明现在有效?

Maf*_*fii 4 .net c# enums c#-6.0

在回答另一个问题时,Jon Skeet提到有一个奇怪的事情正在进行定义enums.他的回答.

他声明,enum只有类型别名而不是框架类型(int有效,Int32不是等)才能重新定义a的基础类型.

public enum Foo : UInt32 {} // Invalid
public enum Bar : uint   {} // Valid
Run Code Online (Sandbox Code Playgroud)

现在我试图重现(在VS2015中使用C#6/Roslyn),我没有得出相同的结论:

public enum TestEnum : UInt32
{

}
Run Code Online (Sandbox Code Playgroud)

public enum MyEnum : uint
{

}
Run Code Online (Sandbox Code Playgroud)

都是完全有效的.为什么会这样?或者改变了什么?


编辑:

所以为了清理事情,这是C#6中的一个变化,尚未记录,并且很快就会记录下来,因为你可以从Roslyn Github上的这个git问题中读到

pok*_*oke 6

现在使用C#6,这当然很奇怪.当前正在进行的规范仍然列出了以下用于在枚举声明中指定基类的语法:

enum_base
    : ':' integral_type
    ;
Run Code Online (Sandbox Code Playgroud)

并且整数类型被定义为实际固定标记:

integral_type
    : 'sbyte'
    | 'byte'
    | 'short'
    | 'ushort'
    | 'int'
    | 'uint'
    | 'long'
    | 'ulong'
    | 'char'
    ;
Run Code Online (Sandbox Code Playgroud)

根据此语言规范判断,解析器应拒绝使用未出现在该静态类型标识符列表中的其他基本类型,并导致语法错误.

鉴于这不是发生的事情,有两种可能性:要么故意更改解析器以接受那里的非别名类型,要么解析器错误地接受这些.

如果我们看一下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<BaseTypeSyntax>();
    tmpList.Add(_syntaxFactory.SimpleBaseType(type));
    baseList = _syntaxFactory.BaseList(colon, tmpList);
    _pool.Free(tmpList);
}
Run Code Online (Sandbox Code Playgroud)

此时,它与"正常"继承代码并没有太大差别.因此,任何类型限制都不适用于语法级别,而是适用于语义级别 - 此时可能已经评估了类型别名.

所以这似乎是一个错误:无论是在规范中还是在解析器中.鉴于规范仍在进行中,这可能会在以后修复.