Что такое "специальный класс"?
после того, как не удалось получить что-то вроде следующего для компиляции:
public class Gen<T> where T : System.Array
{
}
ошибка
ограничение не может быть системой специального класса.Массив'
Я начал задаваться вопросом, что именно и "специальный класс"?
люди часто, кажется, получают тот же вид ошибки, когда они указывают System.Enum В общем ограничении. Я получил те же результаты с System.Object,System.Delegate,System.MulticastDelegate и System.ValueType тоже.
есть ли еще из них? Я не могу найти никакой информации о "специальных классах" в C#.
кроме того, что и настолько особенные о тех классах, что мы не можем использовать их в качестве ограничения универсального типа?
7 ответов:
из исходного кода Roslyn это выглядит как список жестко закодированных типов:
switch (type.SpecialType) { case SpecialType.System_Object: case SpecialType.System_ValueType: case SpecialType.System_Enum: case SpecialType.System_Delegate: case SpecialType.System_MulticastDelegate: case SpecialType.System_Array: // "Constraint cannot be special class '{0}'" Error(diagnostics, ErrorCode.ERR_SpecialTypeAsBound, syntax, type); return false; }источник: Binder_Constraints.cs IsValidConstraintType
Я нашел его с помощью поиска GitHub:"ограничение не может быть особым классом"
Я нашел комментарий Джона Скита от 2008 года по аналогичному вопросу: Почему это
System.Enumограничения не поддержал.Я знаю, что это немного не по теме, но он спросил об этом Эрика Липперта (команда C#), и они дали такой ответ:
во-первых, ваша гипотеза верна; ограничения на ограничения это по большому счету артефакты языка, а не столько CLR. (Бывший у нас для этого функций было бы несколько незначительные вещи, которые мы хотели бы изменение в среде CLR относительно того, как указываются перечислимые типы, но в основном это будет языковая работа.)
во-вторых, я лично хотел бы иметь ограничения делегата, перечисление ограничения и возможность указывать ограничения, которые являются незаконными сегодня потому что компилятор пытается спасти вас от самого себя. (Что это запечатанные типы правовых ограничений, и так далее.)
по данным MSDN это статический список классов:
ошибка компилятора CS0702
ограничение не может быть специальным идентификатором класса следующие типы не могут использоваться в качестве ограничений:
согласно спецификации языка C# 4.0 (закодировано: [10.1.5] ограничения параметров типа) говорит две вещи:
1] тип не должен быть object. Потому что все типы являются производными от Object, такое ограничение не имело бы никакого эффекта, если бы оно было разрешено.
2] Если T не имеет первичных ограничений или ограничений параметров типа, его эффективность базовым классом является Object.
при определении универсального типа можно ограничить типы типов, которые клиентский код может использовать для аргументов типа при создании экземпляра класса. Если клиентский код пытается создать экземпляр класса с помощью типа, который не допускает ограничения, результат-ошибка времени компиляции. Эти ограничения называются ограничениями. Ограничения задаются с помощью ключевого слова where contextual. если вы хотите ограничить универсальный тип ссылочным типом, используйте: class.
public class Gen<T> where T : class { }это запретит универсальный тип от того, чтобы быть типом значения, таким как int или struct и т. д.
кроме того, ограничение не может быть специальным идентификатором класса следующие типы не могут использоваться в качестве ограничений:
в структуре есть определенные классы, которые эффективно передают специальные характеристики всем типам, производным от них но сами не обладают этими характеристиками. Сама среда CLR не налагает запрета на использование этих классов в качестве ограничений, но общие типы, ограниченные ими, не будут приобретать не унаследованные характеристики, как это было бы с конкретными типами. Создатели C# решили, что из-за такого поведения некоторые люди могут запутаться, и они не видят никакой пользы для него, они должны запретить такие ограничения, а не позволить им вести себя так, как они делают в среде CLR.
если бы, например, можно было написать:
void CopyArray<T>(T dest, T source, int start, int count); можно было бы пройтиdestиsourceк методам, которые ожидают аргумент типаSystem.Array; кроме того, можно было бы получить проверку времени компиляции, чтоdestиsourceбыли совместимые типы массивов, но нельзя было бы получить доступ к элементам массива с помощью[]оператор.невозможность использования
Arrayкак ограничение в основном довольно легко обойти, так какvoid CopyArray<T>(T[] dest, T[] source, int start, int count)будет работать почти во всех ситуациях, где Первый метод будет работать. Однако у него есть слабость: первый метод будет работать в сценарии, в котором один или оба аргумента имеют типSystem.Arrayпри отклонении случаев, когда аргументы являются несовместимыми типами массива; добавление перегрузки, где оба аргумента были типаSystem.Arrayсделал бы код принять дополнительные случаи Он должен принять, но и заставить его ошибочно принять случаи, которые он не должен.я нахожу решение запретить большинство специальных ограничений раздражающим. Единственный, который имел бы нулевое семантическое значение, был бы
System.Object[так как если бы это было законно в качестве ограничения, все бы его удовлетворило].System.ValueTypeвероятно, было бы не очень полезно, Так как ссылки типаValueTypeна самом деле не имеют много общего с типами значений, но она, вероятно, могла бы иметь некоторое значение в случаи, связанные с отражением. ОбаSystem.EnumиSystem.Delegateбыло бы несколько реальных применений, но поскольку создатели C# не думали о них, они объявлены вне закона без уважительной причины.
следующее можно найти в CLR через C# 4th Edition:
Первичный Ограничений
параметр типа может указывать нулевые первичные ограничения или одно первичное ограничение. Предварительные выборы ограничение может быть ссылочным типом, который идентифицирует класс, который не запечатан. Вы не можете указать один из следующих специальных ссылочных типов:
Я не думаю, что существует какое-либо официальное определение "специальных классов"/"специальных типов".
вы можете думать о них a типы, которые не могут быть использованы с семантикой "регулярных" типов:
- вы не можете создать их непосредственно;
- вы не можете наследовать пользовательский тип из них напрямую;
- существует некоторая магия компилятора для работы с ними (необязательно);
- прямое использование их экземпляров как минимум бесполезно (необязательно; представьте, что вы создали generic выше, какой общий код вы собираетесь написать?)
P. S. Я хочу добавить
System.Voidв список.
Comments