2016-06-02 10 views
4

Отвечая на другой вопрос, Джон Скит упомянул, что есть странная вещь, имеющая определение enums. His answer.Почему эта декларация enum работает сейчас?

Он утверждает, что redifining базового типа с enum возможно только с типом-псевдонимами, а не с типами каркасных (int действительно, Int32 нет, и т.д.)

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

Теперь я попытался воспроизвести, что (с C# 6/Рослин в VS2015), и я не пришел к такому же выводу:

public enum TestEnum : UInt32 
{ 

} 

и

public enum MyEnum : uint 
{ 

} 

оба действительны. Почему это так? Или что изменилось?


EDIT:

Итак, чтобы убрать вещи, это изменение в C# 6, что не было зарегистрировано ранее, и это будет документировано в ближайшее время, как вы можете прочитать из этого git issue на Roslyn Github

+12

Этот ответ был размещен на '18 окт '08 в 18: 52', который предшествует C# 6 на несколько лет! Казалось бы, они исправили эту аномалию. – ChrisF

+3

его новый компилятор. –

+0

@ChrisF gosh, я был в начальной школе, затем haha ​​ – Mafii

ответ

6

Это, конечно, странно, что это теперь работает с 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 просто не проверяет его, но разбирает любого типа:

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

Либо это надзор в новом компиляторе, либо они приняли решение не иметь эту несогласованность (?) на языке больше.

На данный момент, кажется, не являются официальной спецификацией, только не так официальным выглядящим репозитория, где ведется работа:

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

На данный момент это выглядит не использование псевдонимов для базового типа перечисления должно быть ошибкой. Язык выглядит так же, как и предыдущая официальная спецификация. Но поскольку как компилятор, так и спецификация, похоже, все еще находятся в процессе разработки, трудно сказать, какой из них правильный.

+0

Но разве базовый тип не должен быть расширен до типа фрейма? что, по-видимому, соответствует определению. –

+1

@ DanielA.White: Если вы прочитали вопрос, связанный с OP, то упоминается, что спецификация указывает, что базовый тип должен соответствовать типу 'integ_type', который определяется только как список встроенных ключевых слов C#, и ничего больше. Эта часть одинакова в спецификации прогресса. –

+0

просто глядя на определение 'integ_type', это звучит как везде, где он используется, он должен представлять тип рамки. –

1

Это было намеренное изменение языка в C# 6, спецификации которого были опубликованы только в черновике. Это было такое маленькое изменение, что мы продолжаем забывать, чтобы ввести его в спецификации.

Смотрите также https://github.com/dotnet/roslyn/issues/623

+0

Всегда здорово видеть, что делаются! благодаря – Mafii