C# 7.3 Enum ограничение: Защо не мога да използвам ключовата дума enum?

За да огранича параметър за общ тип да бъде от тип enum, преди това ги ограничих по този начин, което беше най-доброто, което можех да отида за ограничаване на тип T за enums в преди 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 не работи тук за enums. Вярно е, че 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 за генерични продукти не се съпоставя с действителен тип (въпреки че на теория би могло да се съпостави с ValueType). По същия начин, 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