【问题标题】:Why is this enum declaration working now?为什么这个枚举声明现在有效?
【发布时间】:2016-06-02 10:18:47
【问题描述】:

在回答另一个问题时,Jon Skeet 提到 enums 的定义发生了一件奇怪的事情。 His answer.

他指出,重新定义 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 问题中看到的那样

【问题讨论】:

  • 该答案发布在Oct 18 '08 at 18:52,比 C# 6 早了几年!看来他们已经修复了这个异常。
  • 它是一个新的编译器。
  • @ChrisF 天哪,我当时在小学,哈哈
  • @svick 谢谢先生

标签: c# .net enums c#-6.0


【解决方案1】:

现在这在 C# 6 中工作当然很奇怪。当前正在进行的规范仍然列出了以下用于在 enum declarations 中指定基的语法:

enum_base
    : ':' integral_type
    ;

并且整数类型定义为actual fixed tokens

integral_type
    : 'sbyte'
    | 'byte'
    | 'short'
    | 'ushort'
    | 'int'
    | 'uint'
    | 'long'
    | 'ulong'
    | 'char'
    ;

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

鉴于这不是发生的情况,有两种可能性:解析器被故意更改以接受那里的非别名类型,或者解析器错误地接受了这些。

如果我们看一下 Roslyn 的实现,我们就会明白为什么规范中的这个要求没有被强制执行。 enum declaration parser 根本不检查它,而是解析 any 类型:

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);
}

在这一点上,它与code for “normal” inheritance 并没有太大区别。因此,任何类型限制都不适用于语法级别,而是适用于语义级别——在这一点上,类型别名可能已经被评估了。

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

【讨论】:

    【解决方案2】:

    要么是新编译器的疏忽,要么他们决定不再在语言中出现这种不一致 (?)。

    目前似乎没有官方规范,只有一个看起来不太官方的 git 存储库正在完成工作:

    https://github.com/ljw1004/csharpspec/blob/gh-pages/enums.md

    目前看来,不使用底层枚举类型的别名应该是一个错误。该语言看起来与之前的官方规范相同。但由于编译器和规范似乎仍在进行中,很难说哪个是正确的。

    【讨论】:

    • 但是底层类型不是必须扩展为框架类型吗?这似乎符合定义。
    • @DanielA.White:如果您阅读 OP 链接的问题,它提到规范指定基础类型必须匹配 integral_type 生产,该生产仅定义为 C# 内置列表在关键字中,仅此而已。这部分在进行中的规范中是相同的。
    • 只看integral_type的定义,听起来好像在任何地方使用它都必须代表框架类型。
    • integral_type 定义本身只是一个单词列表 ('sbyte' | 'byte' | 'short' | ...),因此它只能引用神奇的 C# 特定关键字。我理解的方式是,在大多数地方谈论类型时,它指的是层次结构中更高的产品,它允许引用任意类或结构,因此允许引用System.Int32 等。枚举位是唯一直接引用的东西integral_type 生产。
    【解决方案3】:

    这是 C# 6 中有意更改的语言,其规范仅以草稿形式发布。这是一个很小的变化,以至于我们总是忘记将其放入规范中。

    另见https://github.com/dotnet/roslyn/issues/623

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多