Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этой статье рассматриваются следующие ошибки компилятора:
- CS0080: Ограничения не допускаются для необобщённых деклараций.
- CS0081: объявление параметров типа должно быть идентификатором, а не типом.
- CS0224: метод с vararg не может быть универсальным, быть в универсальном типе или иметь параметр params.
-
CS0304: не удается создать экземпляр типа переменной, так как он не имеет
new()ограничения. - CS0305: для использования универсального типа требуются аргументы типа N.
- CS0306: тип не может использоваться в качестве аргумента типа.
- CS0307: идентификатор не является универсальным методом. Если вы планировали список выражений, используйте круглые скобки вокруг выражения.
- CS0308: Необобщённый тип или метод нельзя использовать с аргументами типа.
- CS0310: тип должен быть не абстрактным типом с открытым конструктором без параметров, чтобы использовать его в качестве параметра в универсальном типе или методе.
-
CS0311: тип нельзя использовать в качестве параметра
Tтипа в универсальном типе или методе. Неявное преобразование ссылок из типа1 в тип2 отсутствует. - CS0312: Тип "type1" не может использоваться в качестве параметра типа в обобщённом типе или методе. Тип "type1", допускающий значение NULL, не удовлетворяет ограничению.
- CS0313: Тип "type1" нельзя использовать в качестве параметра типа в универсальном типе или методе. Тип "type1", допускающий значение NULL, не соответствует ограничению. Типы, допускающие значение NULL, не могут удовлетворять ограничениям интерфейса.
- CS0314: Этот тип нельзя использовать в качестве параметра типа в обобщенном типе или методе. Преобразование упаковки или преобразование параметра типа невозможно.
-
CS0315: тип нельзя использовать в качестве параметра
Tтипа в обобщённом типе или методе. Нет преобразования упаковки. -
CS0401:
new()ограничение должно быть последним ограничением. -
CS0403: не удается преобразовать значение NULL в параметр типа, так как это может быть ненулевой тип значения. Вместо этого рекомендуется использовать
default(T). - CS0405: повторяющееся ограничение для параметра типа.
- CS0412: параметр: параметр, локальная переменная или локальная функция не могут иметь то же имя, что и параметр типа метода.
-
CS0413: параметр типа нельзя использовать с
asоператором, так как он не имеет ограничения типа класса илиclassограничения. - CS0417: идентификатор: не может предоставлять аргументы при создании экземпляра переменной типа.
-
CS0449: Ограничения
class,struct,unmanaged,notnullиdefaultне могут быть объединены или дублированы и должны быть сначала указаны в списке ограничений. -
CS0450: параметр type: не может указывать как класс ограничений, так и
classstructограничение. -
CS0451:
new()ограничение нельзя использовать с ограничениемstruct. - CS0454: зависимость с циклическим ограничением, включающая параметр типа 1 и параметр типа 2.
- CS0455: параметр type наследует конфликтующие ограничения.
- CS0694: параметр type имеет то же имя, что и содержащий тип или метод.
-
CS0695:
Tне может реализовать оба интерфейса, так как они могут объединиться для некоторых подстановок параметров типа. - CS0698: универсальный тип не может быть производным от типа, так как это класс атрибутов.
- CS0702: ограничение не может быть специальным классом.
- CS0703: Несогласованная доступность: тип ограничения менее доступен, чем объявление.
- CS0706: недопустимый тип ограничения. Тип, используемый в качестве ограничения, должен быть интерфейсом, непечатанным классом или параметром типа.
- CS0717: статический класс: статические классы нельзя использовать в качестве ограничений.
- CS1961: недопустимая дисперсия: параметр типа должен быть допустимым вариантом для типа.
- CS7002: неожиданное использование универсального имени.
- CS8322: не удается передать аргумент с динамическим типом в универсальную локальную функцию с аргументами выводимых типов.
-
CS9011: Ключевое слово
delegateнельзя использовать в качестве ограничения. Вы имели в видуSystem.Delegate? -
CS9012: Неожиданное ключевое слово
record. Вы имели в видуrecord structилиrecord class? - CS9338: Несоответствующая доступность: тип менее доступен, чем класс.
Объявление и именование параметров типа
Следующие ошибки связаны с объявлением и именованием параметров типа в универсальных типах и методах.
- CS0080: ограничения не допускаются для не универсальных объявлений.
- CS0081: объявление параметров типа должно быть идентификатором, а не типом.
- CS0412: параметр: параметр, локальная переменная или локальная функция не могут иметь то же имя, что и параметр типа метода.
- CS0694: параметр type имеет то же имя, что и содержащий тип или метод.
-
CS9012: неожиданное ключевое слово
record. Вы имели в видуrecord structилиrecord class?
Чтобы исправить эти ошибки, убедитесь, что вы объявляете параметры типа с допустимыми идентификаторами, применяйте предложения ограничений только к универсальным объявлениям и избегайте конфликтов именования с другими идентификаторами в области:
- Удалите условие ограничения из необобщённых объявлений (CS0080). Предложение
whereможет использоваться только для универсальных типов и методов, объявляющих параметры типа, так как ограничения определяют требования, которые должны удовлетворять аргументы типа. Если необходимо применить ограничения, сначала добавьте параметры типа в объявление типа или метода. Например, изменитеpublic class MyClass where MyClass : System.IDisposableнаpublic class MyClass<T> where T : System.IDisposable. - Замените фактические имена типов идентификаторами в объявлениях параметров типа (CS0081). Необходимо объявить параметры типа с помощью идентификаторов (например
T,TKeyилиTValue) вместо конкретных типов (напримерint, илиstring). Назначение параметра типа — служить заполнителем, который компилятор заменяет фактическими типами при использовании универсального типа или метода. Например, изменитеpublic void F<int>()наpublic void F<T>(). - Переименуйте параметры типа, локальные переменные или параметры, чтобы избежать конфликтов именования (CS0412, CS0694). Имена параметров типа не могут заслонять идентификаторы в той же области видимости. Они не могут соответствовать имени содержащего типа или метода. Такие конфликты создают неоднозначность о том, на какой идентификатор ссылается. Например, если у вас есть метод
public void F<T>(), вы не можете объявить локальную переменнуюdouble Tвнутри этого метода, и нельзя назвать параметр типа так же, как и его содержащий тип (class C<C>). - Используйте правильный синтаксис объявления записей (CS9012). При объявлении типа записи необходимо использовать
record classилиrecord struct(или толькоrecordдля ссылочного типа). Ключевое словоrecordне может использоваться в позициях, в которых компилятор ожидает синтаксис объявления типов. Например, если вы хотите объявить тип записи, напишитеrecord class MyRecordилиrecord struct MyRecordвместо размещенияrecordтам, где ожидается другое ключевое слово.
Дополнительные сведения см. в разделе "Параметры универсального типа " и "Универсальные типы".
Объявление ограничений и порядок
Следующие ошибки связаны с синтаксисом и упорядочением ограничений для параметров универсального типа:
-
CS0401:
new()ограничение должно быть последним ограничением. -
CS0449: Ограничения
class,struct,unmanaged,notnullиdefaultне могут быть объединены или дублированы и должны быть указаны первыми в списке ограничений. -
CS0450: параметр type: не может указывать как класс ограничений, так и
classstructограничение. -
CS0451: Ограничение
new()нельзя использовать с ограничениемstruct. -
CS9011: ключевое слово
delegateнельзя использовать в качестве ограничения. Вы имели в видуSystem.Delegate?
Ограничения параметров типа должны соответствовать определенному порядку: первичные ограничения (class,, structunmanaged, notnullилиdefault) приходят первым, а затем ограничения интерфейса или класса и, наконец, ограничение конструктораnew(). Некоторые ограничения являются взаимоисключающими и не могут быть объединены.
Чтобы исправить эти ошибки, выполните указанные ниже действия.
- Поместите
new()ограничение в конец списка ограничений (CS0401). Ограничениеnew()должно отображаться после всех других ограничений. Например, изменитеwhere T : new(), IDisposableнаwhere T : IDisposable, new(). - Сначала поместите основные ограничения и не сочетайте взаимоисключающие ограничения (CS0449). В списке ограничений можно указать не более одного из
class,struct,unmanaged,notnullилиdefault, и он должен появиться первым. Ограниченияclassявляются взаимоисключающими, как иstructclass.unmanagedВ nullable контекстеclassуже подразумеваетnotnull, поэтому их нельзя объединить. - Не сочетайте определенное ограничение класса с
struct(CS0450). Если параметр типа ограничен определенным типом класса, это неявно ссылочный тип, который противоречит ограничениюstruct. Удалите ограничение класса илиstructограничение. - Не сочетайте
new()сstruct(CS0451). Все типы значений (структуры) неявно имеют открытый конструктор без параметров, поэтомуnew()ограничение избыточно при сочетании сstruct. Удалите ограничениеnew()при использованииstruct. - Замените
delegateнаSystem.Delegateв предложениях ограничений (CS9011). Ключевоеdelegateслово используется для объявления типов делегатов, а не в качестве ограничения. Чтобы ограничить параметр типа делегированным типам, используйтеSystem.Delegateв качестве типа ограничения. Например, изменитеwhere T : delegateнаwhere T : System.Delegate.
В следующем примере показано правильное упорядочение ограничений:
using System;
// Primary constraint first, then interface constraints, then new()
class C<T> where T : class, IDisposable, new() { }
// struct doesn't need new() - it's implicit
class D<T> where T : struct, IComparable { }
// Delegate constraint using System.Delegate
class E<T> where T : System.Delegate { }
Дополнительные сведения см. в статье Ограничения параметров типа.
Количество аргументов типа и использование
Следующие ошибки связаны с предоставлением правильного числа и типа аргументов типа универсальным типам и методам:
- CS0224: метод с vararg не может быть универсальным, быть в универсальном типе или иметь параметр params.
- CS0305: для использования универсального типа требуются аргументы типа N.
- CS0306: тип не может использоваться в качестве аргумента типа.
- CS0307: идентификатор не является универсальным методом. Если вы планировали список выражений, используйте круглые скобки вокруг выражения.
- CS0308: Не являющийся универсальным тип или метод нельзя использовать с аргументами типа.
- CS7002: неожиданное использование универсального имени.
Чтобы исправить эти ошибки, убедитесь, что укажите точное количество аргументов типа, необходимых универсальному объявлению. Используйте только допустимые типы в качестве аргументов типа. Не применяйте аргументы типа к не универсальным конструкциям:
- Удалите параметры универсального типа или содержащие объявления универсальных типов из методов, использующих
__arglist(CS0224). Ключевое__arglistслово несовместимо с универсальными шаблонами, так как механизмы среды выполнения для обработки списков аргументов переменной конфликтуют с подстановкой типов, необходимой для параметров универсального типа. Это ограничение также применяется к ключевому словуparamsпри его использовании с универсальными методами или методами в универсальных типах. - Укажите точное число аргументов типа, указанных в объявлении универсального типа или метода (CS0305). Каждый параметр универсального типа, объявленный в определении, должен иметь соответствующий аргумент типа при создании экземпляра универсального типа. Компилятор должен знать, какой конкретный тип следует заменить для каждого параметра типа. Например, если класс объявлен как
class MyList<T>, необходимо указать ровно один аргумент типа при его использовании, напримерMyList<int>, неMyList<int, string>. - Используйте только допустимые типы в качестве аргументов типа (CS0306). Типы указателей, такие как
int*илиchar*, нельзя использовать в качестве аргументов типов, поскольку универсальные типы требуют управляемых типов, которые сборщик мусора может отслеживать, а типы указателей являются неуправляемыми. Если вам нужно работать с указателями в универсальном контексте, рассмотрите возможность использованияIntPtrили реструктуризации кода, чтобы избежать смешивания универсальных элементов с небезопасным кодом. - Удалите синтаксис аргумента типа из не универсальных конструкций (CS0307, CS0308). Аргументы типа, заключенные в угловые скобки (например
<int>), могут применяться только к универсальным типам и методам, объявляющим параметры типа. Необходимо полностью удалить аргументы типа или убедиться, что вы импортировали пространство имен, содержащее универсальную версию типа. Например,IEnumerator<T>требует директивуusing System.Collections.Generic;, тогда какIEnumeratorнаходится вSystem.Collections. - Удалите параметры типа из объявлений, которые не поддерживают обобщения (CS7002). Некоторые конструкции, такие как перечисления, не могут быть обобщёнными. Если вам нужен универсальный контейнер для перечисляемых значений, рассмотрите возможность использования универсального класса или структуры.
Дополнительные сведения см. в разделе "Параметры универсального типа " и "Универсальные типы".
Ограничения конструктора
Следующие ошибки связаны с ограничением new() параметров универсального типа:
-
CS0304: не удается создать экземпляр типа переменной, так как он не имеет
new()ограничения. - CS0310: тип должен быть не абстрактным типом с открытым конструктором без параметров, чтобы использовать его в качестве параметра в универсальном типе или методе.
- CS0417: идентификатор: не может предоставлять аргументы при создании экземпляра переменной типа.
Чтобы исправить эти ошибки, добавьте new() ограничение к параметрам типа, которые необходимо создать, убедитесь, что аргументы типа имеют открытые конструкторы без параметров и не передают аргументы при создании экземпляров параметров типа:
- Добавьте ограничение
new()к объявлению параметра типа (CS0304). При использованииnewоператора для создания экземпляра параметра типа в универсальном типе или методе компилятор должен гарантировать, что любой аргумент типа, предоставленный во время выполнения, имеет доступный конструктор без параметров. Ограничениеnew()обеспечивает эту гарантию во время компиляции, позволяя компилятору создавать соответствующий код экземпляра. Например, если у вас естьclass C<T>с элементомT t = new T();, необходимо изменить объявление наclass C<T> where T : new(). - Убедитесь, что аргументы типа, используемые с
new()параметрами ограниченного типа, имеют публичные конструкторы без параметров (CS0310). Если универсальный тип или метод объявляетnew()ограничение для параметра типа, любой конкретный тип, используемый в качестве аргумента типа, должен быть не абстрактным и должен предоставлять открытый конструктор без параметров. Если тип имеет только недоступные конструкторы (напримерprivate,protectedконструкторы) или только конструкторы с параметрами, он не может удовлетворитьnew()ограничение. Чтобы устранить эту ошибку, добавьте в тип открытый конструктор без параметров или используйте другой аргумент типа, который уже имеет один. - Удалите аргументы конструктора при инициализации типовых параметров (CS0417). Ограничение
new()гарантирует только существование конструктора без параметров, поэтому невозможно передать аргументыnew T(arguments), так как компилятор не может проверить наличие конструктора с указанными типами параметров в типах, заменяемых.TЕсли необходимо создать экземпляры с определенными аргументами, рассмотрите возможность использования фабричных методов, абстрактных фабричных шаблонов или определенных ограничений базового класса или интерфейса, которые определяют требуемое поведение при построении.
Для получения дополнительной информации см. раздел «Ограничения для параметров типов» и new() ограничение.
Удовлетворение ограничений и преобразования
Следующие ошибки связаны с аргументами типа, не удовлетворяющими ограничениям параметров универсального типа:
-
CS0311: Этот тип нельзя использовать в качестве параметра
Tв универсальном типе или методе. Отсутствует неявное преобразование ссылок. - CS0312: тип нельзя использовать в качестве параметра типа в универсальном типе или методе. Тип, допускающий значение NULL, не удовлетворяет ограничению.
- CS0313: тип нельзя использовать в качестве параметра типа в универсальном типе или методе. Тип, допускающий значение NULL, не удовлетворяет ограничению. Типы, допускающие значение NULL, не могут удовлетворять ограничениям интерфейса.
- CS0314: тип нельзя использовать в качестве параметра типа в универсальном типе или методе. Преобразование в бокс или преобразование параметров типа отсутствует.
-
CS0315: Тип нельзя использовать в качестве параметра
Tтипа в обобщенном типе или методеTypeorMethod<T>. Преобразования упаковки нет.
Чтобы исправить эти ошибки, используйте аргументы типа, удовлетворяющие всем ограничениям с помощью соответствующих преобразований, убедитесь, что производные классы повторяют ограничения базового класса и понимают, что типы значений, допускающие значение NULL, имеют особые требования к ограничению:
- Измените аргумент типа на тот, который имеет неявное преобразование ссылок на тип ограничения (CS0311). Если параметр типа имеет ограничение, например
where T : BaseType, то любой аргумент типа должен быть преобразуем вBaseTypeчерез неявное преобразование ссылок или тождественное преобразование. Аргумент типа должен бытьBaseType, производным отBaseTypeили реализоватьBaseType, еслиBaseTypeявляется интерфейсом. Неявные числовые преобразования (например, от доshortint) не удовлетворяют ограничениям параметров универсального типа, так как эти преобразования являются преобразованиями значений, а не ссылочными преобразованиями. - Повторите ограничения параметров типа базового класса в любом объявлении производного класса (CS0314). Если производный универсальный класс наследует от базового универсального класса, имеющего ограничения на его параметры типа, производный класс должен объявить те же ограничения для соответствующих параметров типа. Необходимо повторить эти ограничения, так как компилятору необходимо проверить, что аргументы типа, предоставленные производному классу, удовлетворяют требованиям базового класса. Например, если у вас есть
public class A<T> where T : SomeClass, то любой класс, производный от него, должен быть объявлен какpublic class B<T> : A<T> where T : SomeClass. - Используйте типы значений, не допускающие значение NULL, или измените тип ограничения (CS0312, CS0313). Типы значений, допускающие значение NULL (например
int?, отличаются от их базовых типов значений и не удовлетворяют тем же ограничениям). Междуint?иintнет неявного преобразования, а типы значений, допускающие NULL, не могут удовлетворить ограничения интерфейса, потому что оболочка NULL не реализует интерфейс, хотя базовый тип значения реализует его. Чтобы устранить эти ошибки, используйте ненулевую форму типа значения в качестве аргумента типа или измените ограничение, чтобы приниматьobjectили тип nullable ссылки, если это подходит. - Убедитесь, что аргументы типов удовлетворяют ограничениям ссылочного типа или класса (CS0315). Если параметр типа ограничен типом класса (например
where T : SomeClass, вы не можете использовать тип значения (структуру) в качестве аргумента типа, так как преобразование бокса не удовлетворяет связи ограничений. Для ограничения требуется ссылочный тип, который имеет отношение наследования или реализации с типом самого ограничения. Чтобы устранить эту ошибку, измените структуру на класс, если это семантически оправдано, или удалите ограничение класса, если универсальный тип может работать с типами-значениями.
Дополнительные сведения см. в разделе "Ограничения" для параметров типа и неявных преобразований.
Ограничения использования универсального типа
Следующие ошибки связаны с ограничениями на использование универсальных типов:
-
CS0403: не удается преобразовать значение NULL в параметр типа, так как это может быть ненулевой тип значения. Вместо этого рекомендуется использовать
default(T). -
CS0413: параметр типа нельзя использовать с
asоператором, так как он не имеет ограничения типа класса илиclassограничения. - CS0695: Тип не может реализовать оба интерфейса, поскольку они могут быть объединены для некоторых подстановок параметров типа.
- CS0698: универсальный тип не может быть производным от типа, так как это класс атрибутов.
- CS8322: не удается передать аргумент с динамическим типом в универсальную локальную функцию с аргументами выводимых типов.
- CS9338: Несоответствующая доступность: тип менее доступен, чем класс.
Чтобы исправить эти ошибки, используйте default вместо null параметров без ограничений типа, добавьте ограничения классов при использовании as оператора, избегайте конфликтов объединения интерфейса, не создавайте универсальные классы атрибутов и убедитесь, что аргументы типов соответствуют видимости их содержащих членов:
- Замените присваивания
nullнаdefault(T)или добавьте ограничениеclass(CS0403). При назначенииnullпараметру без ограничений компилятор не может гарантировать, что аргумент типа является ссылочным типом, принимаюющимnullзначения, так как это может быть тип значения, напримерintилиstruct, который не может бытьnull. Чтобы устранить эту ошибку, используйтеdefault(T), который предоставляет подходящее значение по умолчанию для любого типа (null для ссылочных типов, ноль или пустая строка для типов значений) или добавьте ограничениеclassк параметру типа, если требуется семантика ссылочного типа и хотите позволить назначенияnull. - Добавьте
classили конкретное ограничение типа при использованииasоператора (CS0413). Операторasвыполняет безопасное приведение типа, результатом которого являетсяnull, если преобразование завершается ошибкой, но это поведение несовместимо с типами значений, поскольку они не могут бытьnull. При использованииasс параметром без ограничений компилятор не может гарантировать, что аргумент типа не является типом значения, поэтому он отклоняет код. Чтобы устранить эту ошибку, добавьте ограничениеclassили конкретное ограничение для ссылочного типа (например,where T : SomeClass), чтобы гарантировать, что параметр типа всегда является ссылочным типом, который может правильно обрабатывать результат неудачного приведенияnull. - Избегайте реализации одного и того же универсального интерфейса несколько раз с параметрами типа, которые могут быть объединены (CS0695). Когда класс реализует универсальный интерфейс несколько раз с разными параметрами типа (например
class G<T1, T2> : I<T1>, I<T2>), существует риск, что кто-то может создать экземпляр класса с одинаковым типом для обоих параметров (G<int, int>), что приведет к конфликту, поскольку класс будет реализовыватьI<int>дважды. Чтобы устранить эту ошибку, реализуйте интерфейс только один раз, переструктурируйте параметры типа, чтобы предотвратить объединение, или использовать отдельные не универсальные классы для разных специализаций. - Удалите параметры универсального типа из классов атрибутов (CS0698).
Замечание
Эта ошибка не создается в текущих версиях C#, так как теперь поддерживаются универсальные атрибуты.
- Явно укажите аргументы типа при передаче динамических значений универсальным локальным функциям (CS8322). При передаче аргумента
dynamicв универсальную локальную функцию компилятор не может выводить аргументы типа, так как фактический тип не известен до выполнения. Чтобы устранить эту ошибку, явно укажите аргумент типа (например,LocalFunc<int>(d)), приведите динамическое значение к ожидаемому типу или используйте нединамическую переменную. - Убедитесь, что аргументы типа, используемые в общедоступных или защищенных сигнатурах, по крайней мере, так же доступны, как и член, который их использует (CS9338). Общедоступный или защищенный универсальный член должен использовать аргументы типа, которые являются общедоступными. В противном случае внешний код не мог правильно ссылаться или использовать подпись члена. Например, если у вас есть `
public class Container<T>`, где `T` является внутренним типом, внешние сборки могут видеть `Container`, но не могут правильно с ним работать, потому что они не могут видеть `T`. Чтобы устранить эту ошибку, сделайте аргумент типа общедоступным или уменьшите специальные возможности члена, используя его для сопоставления специальных возможностей аргумента типа.
Дополнительные сведения см. в разделе "Ограничения" для параметров типа, выражений значений по умолчанию и атрибутов.
Допустимые типы ограничений
Следующие ошибки связаны с использованием недопустимых типов в качестве ограничений для параметров универсального типа:
- CS0405: повторяющееся ограничение для параметра типа.
- CS0702: ограничение не может быть специальным классом.
- CS0703: Несогласованная доступность: тип ограничения менее доступен, чем объявление.
- CS0706: недопустимый тип ограничения. Тип, используемый в качестве ограничения, должен быть интерфейсом, непечатанным классом или параметром типа.
-
CS0717:
static classстатические классы нельзя использовать в качестве ограничений.
Ограничение должно быть интерфейсом, непечатанным классом или параметром типа. Некоторые типы недопустимы в качестве ограничений из-за их специального значения в системе типов .NET или из-за того, что они не могут быть унаследованы.
Чтобы исправить эти ошибки, выполните указанные ниже действия.
- Удалите повторяющиеся ограничения (CS0405). Каждое ограничение может отображаться только один раз в предложении ограничения. Если у вас есть
where T : I, I, удалите дубликат. - Не используйте специальные классы в качестве ограничений (CS0702). Типы Objectи ArrayValueType не могут использоваться в качестве ограничений. Каждый тип уже является производным от
Object, поэтому ограничение для него не предоставляет никакого значения.ArrayиValueTypeявляются абстрактными базовыми типами, которые нельзя наследовать напрямую. Если требуется поведение массива, используйтеIList<T>илиIEnumerable<T>вместо этого. - Убедитесь, что типы ограничений не менее доступны, чем универсальный тип (CS0703). Общедоступный универсальный тип не может иметь ограничений с использованием внутренних типов, так как внешний код не сможет предоставлять допустимые аргументы типа. Либо сделать тип ограничения общедоступным, либо уменьшить доступность универсального типа.
- Используйте только интерфейсы, непечатанные классы или параметры типа в качестве ограничений (CS0706). Нельзя использовать массивы, запечатанные классы, структуры, перечисления или другие недопустимые типы в качестве ограничений. Если требуется определенное поведение, рассмотрите возможность использования интерфейса, реализуемого требуемыми типами.
- Не используйте статические классы в качестве ограничений (CS0717). Статические классы нельзя расширить, так как они содержат только статические элементы. Тип не может существовать, производный от статического класса, что делает его бесполезным в качестве ограничения. Вместо этого используйте нестатический класс или интерфейс.
В следующем примере показаны допустимые типы ограничений:
public interface IMyInterface { }
public class MyBaseClass { }
// Valid: interface constraint
class A<T> where T : IMyInterface { }
// Valid: non-sealed class constraint
class B<T> where T : MyBaseClass { }
// Valid: type parameter constraint
class C<T, U> where T : U { }
Дополнительные сведения см. в статье Ограничения параметров типа.
Конфликты ограничений и циклические зависимости
Следующие ошибки связаны с конфликтами между ограничениями или циклическими зависимостями в объявлениях ограничений:
- CS0454: зависимость с циклическим ограничением, включающая параметр типа 1 и параметр типа 2.
- CS0455: параметр type наследует конфликтующие ограничения.
Ограничения не могут создавать циклические зависимости, а параметры типа не могут наследовать конфликтующие ограничения, которые невозможно удовлетворить одновременно.
Чтобы исправить эти ошибки, выполните указанные ниже действия.
- Удалите зависимости кругового ограничения (CS0454). Параметр типа не может напрямую или косвенно зависеть от себя с помощью ограничений. Например,
where T : U where U : Tсоздает циклическую зависимость, так какTзависит отU, аUзависит отT. Разорвать цикл, удалив одно из ограничений. - Удалите конфликтующие наследуемые ограничения (CS0455). Параметр типа не может быть ограничен несколькими несвязанными классами, так как C# не поддерживает наследование нескольких классов. Аналогично, его нельзя ограничить одновременно как
struct, так и типом класса, поскольку эти ограничения взаимоисключают друг друга. Переструктурируйте иерархию типов или удалите одно из конфликтующих ограничений.
В следующем примере показаны проблемы:
// CS0454: Circular dependency - T depends on U and U depends on T
class Circular<T, U> where T : U where U : T { }
// CS0455: Conflicting constraints - U can't derive from both B and B2
public class B { }
public class B2 { }
public class G<T> where T : B
{
public class N<U> where U : B2, T { }
}
Дополнительные сведения см. в статье Ограничения параметров типа.
Вариантность параметров типа
Следующая ошибка связана с модификаторами дисперсии для параметров универсального типа:
- CS1961: недопустимая дисперсия: параметр типа должен быть допустимым вариантом для типа.
Модификаторы вариации (in для контравариации, out для ковариации) управляют использованием параметров типа в объявлениях интерфейса и делегатов. Параметр типа ковариантного (out) может отображаться только в выходных позициях (возвращаемых типах), а параметр типа контравариантного (in) может отображаться только в входных позициях (типах параметров).
Чтобы исправить эту ошибку, выполните указанные ниже действия.
- Используйте
out(ковариант) для параметров типа, которые отображаются только в возвращаемых типах. Ковариация позволяет использовать более производный тип, где ожидается менее производный тип. - Используйте
in(contravariant) для параметров типа, которые отображаются только в типах параметров. Контравариантность позволяет использовать менее производный тип, где ожидается более производный тип. - Удалите модификатор дисперсии, если параметр типа должен отображаться как в входных, так и в выходных позициях.
В следующем примере показано правильное и неправильное использование дисперсии:
// Incorrect: out T can't appear in input position
interface IWrong<out T>
{
void Method(T arg); // CS1961
}
// Correct: out T only in output positions
interface ICovariant<out T>
{
T GetValue();
}
// Correct: in T only in input positions
interface IContravariant<in T>
{
void Process(T arg);
}
// No modifier needed for both input and output
interface IInvariant<T>
{
T Transform(T arg);
}
Дополнительные сведения см. в разделе «Ковариация и контравариантность в универсальных шаблонах».