Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
497 views
in Technique[技术] by (71.8m points)

c# - Why is this enum declaration working now?

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 redifining the underlying type of an enum is only possible with the type-aliases and not with the framework types (int is valid, Int32 not, etc.)

public enum Foo : UInt32 {} // Invalid
public enum Bar : uint   {} // Valid

Now I tried to reproduce that (with C#6/Roslyn in VS2015), and I didn't come to the same conclusion:

public enum TestEnum : UInt32
{

}

and

public enum MyEnum : uint
{

}

are both totally valid. Why is that so? Or has what changed?


EDIT:

So to clear up things, it was a change in C#6, that has not been documented yet, and it will be documented soon, as you can read from this git issue on the Roslyn Github

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...