C # 7.3 Ограничение Enum: почему я не могу использовать ключевое слово enum?

Чтобы ограничить параметр универсального типа типом перечисления, я ранее ограничивал их таким образом, что было лучшим, что я мог сделать для ограничения типа T для перечислений в до-C # 7.3:

void DoSomething<T>() where T : struct, IComparable, IConvertible, IFormattable

Теперь в C # 7.3 добавлена ​​новая функция, ограничивающая общий тип System.Enum. Я пробовал использовать ограничение enum в обновлении VS2017 15.7, выпущенном сегодня, и он успешно компилируется, когда я пишу его так (учитывая, что у меня есть директива using System;):

void DoSomething<T>() where T : Enum

Однако использование ключевого слова enum не работает и заставляет компилятор выдавать следующие ошибки (есть еще ошибки, ожидающие тела метода, но я думаю, что здесь не стоит упоминать):

void DoSomething<T>() where T : enum
                                ^ error CS1031: Type expected
                                  error CS1002: ; expected
                                    ^ error CS1001: Identifier expected
                                      error CS1514: { expected
                                      error CS1513: } expected

Поскольку для структур работает ограничение struct, я не понимаю, почему enum здесь не работает для перечислений. Это правда, что enum не отображается на фактический тип, как int для Int32, но я думал, что он должен вести себя так же, как ограничение struct.

Я просто попал в ловушку экспериментальной функции, которая еще не полностью реализована, или это было сделано специально в спецификации (почему?)?


person Ray    schedule 07.05.2018    source источник
comment
В то время как string является псевдонимом для типа String, это неверно для ключевого слова enum и типа Enum.   -  person    schedule 07.05.2018
comment
Вот что я имел в виду в своем последнем абзаце. Ограничение struct также не является псевдонимом для определенного типа, но возможно.   -  person Ray    schedule 07.05.2018
comment
struct предназначен для типов значений, а не только для структуры, аналогично class для всех ссылочных типов   -  person Mrinal Kamboj    schedule 07.05.2018
comment
проверьте это возможное решение stackoverflow.com/a/79903/1559611   -  person Mrinal Kamboj    schedule 07.05.2018
comment
@MrinalKamboj В этом есть смысл. Хотя я думаю, что тогда можно было бы возразить, что эти ключевые слова обрабатывают свои собственные конкретные случаи, и enum должен был поступить так же. О вашей ссылке: с C # 7.3 использование Enum (а не ключевое слово enum) было бы лучшим решением. Вопрос только в том, почему ключевое слово не предназначено для работы (на данный момент).   -  person Ray    schedule 07.05.2018
comment
Эта реализация меня поймала. Мой вопрос Почему общий тип, ограниченный Enum, не может квалифицироваться как «структура»? может или не может быть представляет интерес :)   -  person Stephen Kennedy    schedule 11.05.2018


Ответы (1)


Ограничение struct для универсальных шаблонов не отображается на фактический тип (хотя теоретически оно может отображаться на _ 2_). Точно так же enum не отображает чисто на фактические типы, как это делают string, int или long, он устанавливает специальный синтаксис для создания класса символьных констант, которые отображаются в целочисленные значения; следовательно, public enum Stuff вместо public class Stuff : Enum. Обратите внимание, что если бы последнее было реализовано вместо этого, это было бы более тонким, поскольку он изменил бы синтаксис на основе унаследованного типа вместо изменения синтаксиса на основе ключевого слова, отличного от class.

Итак, в заключение, да, where T : enum не предназначен для работы, потому что enum - это ключевое слово, а не псевдоним типа. Если вы действительно хотите увидеть, как это работает, потому что enum по крайней мере пахнет псевдонимом типа в подобном контексте, иди запросите его!

РЕДАКТИРОВАТЬ: для некоторой исторической справки вот вопрос из 2008 года указывая, что Enum не было допустимым ограничением, поскольку это особый класс.

person David    schedule 07.05.2018
comment
Думаю, это лучшее объяснение на данный момент. Я не смог найти других на GitHub, где обсуждалась реализация этой функции. Как ни странно, люди изначально предоставили образцы, в которых также использовалось ключевое слово enum, но в конце концов это так и не было реализовано. - person Ray; 08.05.2018
comment
@RayKoopa Кроме того, я немного удивлен, что если у вас есть только where T : Enum, то компилятор позволит вам использовать сам абстрактный базовый тип System.Enum (ссылочный тип!) Для T. Так что вы могли DoSomething<Enum>();. Чтобы этого избежать, действительно разрешено делать where T : struct, Enum. Мне кажется, это то, чего вы хотите в 99,9% случаев! Ах, теперь я вижу, что есть связанная ветка именно по этому поводу. - person Jeppe Stig Nielsen; 29.05.2018