Why is this enum declaration working now?

前端 未结 3 610
渐次进展
渐次进展 2020-12-21 01:50

While answering another question, Jon Skeet mentioned that there is a weird thing going on with the definition of enums. His answer.

He states that redi

相关标签:
3条回答
  • 2020-12-21 02:29

    This was an intentional language change in C# 6, whose specs have only been published in draft form. It was such a small change that we keep forgetting to put it into the specs.

    See also https://github.com/dotnet/roslyn/issues/623

    0 讨论(0)
  • 2020-12-21 02:39

    Either it's an oversight in the new compiler or they made a decision not to have that inconsistency (?) in the language anymore.

    At the moment there doesn't seem to be an official specification, only a not-so-official-looking git repository where work is being done:

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

    At the moment it looks like not using the aliases for the underlying enum type should be an error. The language looks to be the same as the previous official spec. But since both the compiler and spec seem to still be works in progress, it's hard to say which one is correct.

    0 讨论(0)
  • 2020-12-21 02:49

    It’s certainly odd that this is working now with C# 6. The current in-progress specification still lists the following grammar for specifying a base in enum declarations:

    enum_base
        : ':' integral_type
        ;
    

    And the integral types are defined as actual fixed tokens:

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

    Judging by this language specification, using some other base type that does not appear in that list of static type identifiers should be rejected by the parser and cause a syntax error.

    Given that that’s not what happens, there are two possibilities: Either the parser was changed deliberately to accept the non-aliased types there, or the parser incorrectly accepts those.

    If we look at the implementation of Roslyn, then we can see why this requirement in the specification is not enforced. The enum declaration parser simply does not check for it but parses any type:

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

    At this point, it does not really differ much from the code for “normal” inheritance. So any type restriction does not apply on the syntax level, but on the semantic level—at which point type alias are probably already evaluated.

    So this seems to be a bug: Either in the specification, or in the parser. Given that the specification is still a work in progress, this might be fixed later.

    0 讨论(0)
提交回复
热议问题