本文介绍以下编译器错误:
- CS0080:不允许 对非泛型声明使用约束。
- CS0081: 类型参数声明必须是非类型的标识符。
- CS0224: 具有 vararg 的方法不能为泛型、处于泛型类型或具有参数参数。
-
CS0304: 无法创建变量类型的实例,因为它没有
new()约束。 - CS0305: 使用泛型类型需要 N 类型参数。
- CS0306: 类型不能用作类型参数。
- CS0307: “标识符”不能与类型参数一起使用。
- CS0308: 非泛型类型或方法不能与类型参数一起使用。
- CS0310: 类型必须是具有公共无参数构造函数的非抽象类型,才能将其用作泛型类型或方法中的参数。
-
CS0311: 类型不能用作泛型类型或方法中的类型参数
T。没有从“type1”到“type2”的隐式引用转换。 - CS0312: 类型“type1”不能用作泛型类型或方法中的类型参数。可为 null 的类型“type1”不满足“constraint”的约束。
- CS0313:类型“type1”不能用作泛型类型或方法中的类型参数。可为 null 的类型“type1”无法满足“constraint”约束。可为 null 的类型不能满足任何接口约束。
- CS0314:该类型不能用作泛型类型或泛型方法中的类型参数。从“type”到“constraint”不存在装箱转换或类型参数转换。
-
CS0315:该类型不能在泛型类型或方法中用作类型参数
T。不存在从 'type' 到 'constraint' 的装箱转换。 -
CS0401: 该
new()约束必须是指定的最后一个限制约束。 -
CS0403: 无法将 null 转换为类型参数,因为它可能是不可为 null 的值类型。请考虑改用
default(T)。 - CS0405: 类型参数的重复约束。
- CS0406:类类型约束“constraint”必须位于任何其他约束之前。
- CS0409: 已为类型参数“type parameter”指定约束子句。类型参数的所有约束都必须在单个 where 子句中指定。
- CS0411: 无法从用法推断方法“method”的类型参数。请尝试显式指定类型参数。
- CS0412:参数:参数、局部变量或本地函数不能与方法类型参数同名。
-
CS0413: 类型参数不能与运算符一起使用
as,因为它没有类类型约束,也没有class约束。 - CS0417: 标识符:创建变量类型的实例时无法提供参数。
-
CS0449:
class不能组合或复制约束,structunmanagednotnulldefault并且必须先在约束列表中指定。 -
CS0450:类型参数:不能同时指定约束类或
classstruct约束。 -
CS0451:
new()约束不能与struct约束一起使用。 - CS0452: 类型“type name”必须是引用类型,才能将其用作泛型类型或方法“generic”中的参数“参数名称”。
- CS0453: 类型“type name”必须是不可为 null 的值类型,才能将其用作泛型类型或方法“generic”中的参数“参数名称”。
- CS0454: 涉及类型参数 1 和类型参数 2 的循环约束依赖项。
- CS0455: 类型参数继承冲突约束“constraint1”和“constraint2”。
- CS0456: 类型参数“type parameter 1”具有“结构”约束,因此“type parameter 1”不能用作“type parameter 2”的约束。
- CS0693: 类型参数“type parameter”与外部类型“type”中的类型参数同名。
- CS0694: 类型参数的名称与包含类型或方法的名称相同。
- CS0695: “type”不能同时实现“interface1”和“interface2”,因为它们可能会统一某些类型参数替换。
- CS0698: 泛型类型无法从类型派生,因为它是属性类。
- CS0699: “generic”不定义类型参数“identifier”。
- CS0701: “identifier”不是有效的约束。用作约束的类型必须是接口、非密封类或类型参数。
- CS0702: 约束不能是特殊类。
- CS0703: 可访问性不一致:约束类型的可访问性低于声明。
- CS0704: 无法在“type”中执行非虚拟成员查找,因为它是类型参数。
- CS0706: 约束类型无效。用作约束的类型必须是接口、非密封类或类型参数。
- CS0717: 静态类:静态类不能用作约束。
- CS0718: “type”:静态类型不能用作类型参数。
- CS1720: 表达式始终会导致 System.NullReferenceException,因为“泛型类型”的默认值为 null。
- CS1763: “parameter”的类型为“type”。字符串以外的引用类型的默认参数值只能使用 null 进行初始化。
- CS1948: 范围变量“name”不能与方法类型参数同名。
- CS1960: 差异修饰符无效。只能将接口和委托类型参数指定为变体。
- CS1961: 差异无效:类型参数在“type”上必须协变有效。“type parameter”是逆变的。
- CS3024: 约束类型“type”不符合 CLS。
- CS7002: 意外使用泛型名称。
- CS8322: 无法将具有动态类型的参数传递给具有推断类型参数的泛型本地函数。
- CS8375: “new()”约束不能与“非托管”约束一起使用。
- CS8377:类型“type”必须是不可为 null 的值类型,并且在任何嵌套级别中的所有字段也都必须是不可为 null 的值类型,才能将其用作泛型类型或方法“generic”的参数“parameter”。
- CS8379: 类型参数“type parameter 1”具有“非托管”约束,因此“类型参数 1”不能用作“类型参数 2”的约束。
- CS8380: “type”:不能同时指定约束类和“非托管”约束。
- CS8387: 类型参数“type parameter”与外部方法“method”中的类型参数同名。
- CS8389:当前 上下文中不允许省略类型参数。
- CS8427: 不能在具有“in”或“out”类型参数的接口中声明枚举、类和结构。
- CS8665:方法“method”为类型参数“type parameter”指定了“class”约束,但重写或显式实现的对应方法“method”的相应类型参数“type parameter”不是引用类型。
- CS8666: 方法“method”指定类型参数“type parameter”的“结构”约束,但重写或显式实现的方法“method”的相应类型参数“type parameter”不是不可为 null 的值类型。
- CS8822:方法“method”为类型参数“type parameter”指定了“default”约束,但重写或显式实现的方法“method”的相应类型参数“type parameter”被约束为引用类型或值类型之一。
- CS8823: “默认”约束仅在重写和显式接口实现方法上有效。
- CS8893: “type”不是“UnmanagedCallersOnly”的有效调用约定类型。
- CS8894: 不能对具有“UnmanagedCallersOnly”特性的方法使用“type”作为参数或返回类型。
- CS8895: 使用“UnmanagedCallersOnly”属性的方法不能具有泛型类型参数,也不能在泛型类型中声明。
- CS8896: “UnmanagedCallersOnly”只能应用于普通静态非抽象、非虚拟方法或静态本地函数。
-
CS9011: 关键字
delegate不能用作约束。你的意思是System.Delegate吗? -
CS9012: 意外关键字
record。你的意思是record struct还是record class? - CS9338:访问级别不一致:类型的访问性低于类。
类型参数声明和命名
- CS0080:不允许 对非泛型声明使用约束。
- CS0081: 类型参数声明必须是非类型的标识符。
- CS0412:参数:参数、局部变量或本地函数不能与方法类型参数同名。
- CS0693: 类型参数“type parameter”与外部类型“type”中的类型参数同名。
- CS0694: 类型参数的名称与包含类型或方法的名称相同。
- CS0699: “generic”不定义类型参数“identifier”。
- CS1948: 范围变量“name”不能与方法类型参数同名。
- CS8387: 类型参数“type parameter”与外部方法“method”中的类型参数同名。
-
CS9012: 意外关键字
record。你的意思是record struct还是record class?
这些错误与在泛型类型和方法中声明和命名类型参数的方式相关。 类型参数名称必须是有效的标识符,不得与作用域中的其他标识符冲突,并且必须显示在声明的类型参数列表中。
- 从非泛型声明中删除约束子句(CS0080)。
where子句只能用于声明了类型参数的泛型类型和方法。 如果需要应用约束,请先向类型或方法声明添加类型参数。 - 将实际类型名称替换为类型参数声明(CS0081)中的标识符。 必须使用标识符(如
T、TKey或TValue)而不是具体类型(如int或string)声明类型参数。 类型参数的目的在于作为一个占位符,在泛型类型或方法被使用时,编译器会将其替换为实际的类型。 - 重命名类型参数、局部变量、参数或范围变量以避免命名冲突(CS0412、 CS0694、 CS1948)。 类型参数名称不能在同一范围内隐藏标识符,它们与包含的类型或方法的名称不匹配。 LINQ 范围变量也不能重复使用方法的类型参数名称。 此类冲突会创建关于要引用的标识符的歧义。
- 对阴影外部参数(CS0693、 CS8387)的内部类型参数使用不同的名称。 当泛型成员(如方法或嵌套类型)位于泛型类或方法内时,内部类型参数不一定与外部类型相同。 为它们提供同一名称会导致对引用哪个类型参数产生混淆。 为内部类型参数使用不同的名称。
- 确保在类型参数列表中声明约束子句中的所有类型参数(CS0699)。 子
where句只能引用泛型声明中出现的类型参数。 如果where子句中的名称与任何已声明的类型参数都不匹配,请检查是否存在输入错误或拼写错误。 - 使用正确的记录声明语法(CS9012)。 声明记录类型时,必须使用
record class或record struct(或仅record用于引用类型)。record仅关键字就不能出现在编译器需要其他声明语法的位置。
约束声明和排序
-
CS0401: 该
new()约束必须是指定的最后一个限制约束。 - CS0406:类类型约束“constraint”必须位于任何其他约束之前。
- CS0409: 已为类型参数“type parameter”指定约束子句。类型参数的所有约束都必须在单个 where 子句中指定。
-
CS0449:
class不能组合或复制约束,structunmanagednotnulldefault并且必须先在约束列表中指定。 -
CS0450:类型参数:不能同时指定约束类或
classstruct约束。 -
CS0451:约束
new()不能与约束struct一起使用。 - CS8375: “new()”约束不能与“非托管”约束一起使用。
- CS8380: “type”:不能同时指定约束类和“非托管”约束。
-
CS9011: 关键字
delegate不能用作约束。你的意思是System.Delegate吗?
类型参数的约束必须遵循特定的顺序:主要约束(class、、structunmanaged或notnulldefault)先是类类型约束,然后是类类型约束,后跟接口约束,最后是new()构造函数约束。 某些约束是相互排斥的,不能组合。 单个类型参数的所有约束都必须显示在单个 where 子句中。
- 将
new()约束置于约束列表的末尾(CS0401)。 该new()约束必须出现在所有其他约束之后。 例如,将where T : new(), IDisposable更改为where T : IDisposable, new()。 - 将类类型约束置于接口约束(CS0406)之前。 将类型参数与接口一起约束到特定基类时,必须首先显示该类。 例如,将
where T : IDisposable, MyBaseClass更改为where T : MyBaseClass, IDisposable。 - 将类型参数的所有约束合并为单个
where子句(CS0409)。 不能对同一类型参数使用多个where子句。 将它们合并到一个子句中:更改为where T : I where T : new()where T : I, new()。 仅当多个where子句面向不同的类型参数时才有效。 - 先放置主要约束,不合并互斥约束(CS0449)。 最多可以指定一个
class、struct、unmanaged、notnull或default,并且它必须首先出现在约束列表中。 约束class和struct是相互排斥的,class和unmanaged也是如此。 - 不要将特定类约束与
class、struct或unmanaged组合使用(CS0450、CS8380)。 如果类型参数被约束为特定的类类型,它会隐式地成为引用类型,这与struct约束或unmanaged约束相矛盾。 删除类约束或主约束。 - 请勿与
new()或struct(unmanaged、CS8375)组合使用。 所有值类型都隐式具有公共无参数构造函数,因此约束new()在与struct结合使用时是冗余的。 这同样适用于unmanaged,这意味着struct。 删除new()约束。 - 用
delegate替换约束子句中的System.Delegate(CS9011)。 关键字delegate用于声明委托类型,而不是作为约束。 若要将类型参数约束为委托类型,请System.Delegate用作约束类型。
有关详细信息,请参阅类型参数的约束。
有效约束类型
- CS0405: 类型参数的重复约束。
- CS0701: “identifier”不是有效的约束。用作约束的类型必须是接口、非密封类或类型参数。
- CS0702: 约束不能是特殊类。
- CS0703: 可访问性不一致:约束类型的可访问性低于声明。
- CS0706: 约束类型无效。用作约束的类型必须是接口、非密封类或类型参数。
- CS0717: 静态类:静态类不能用作约束。
- CS3024: 约束类型“type”不符合 CLS。
约束必须是接口、非密封类或类型参数。 由于某些类型在 .NET 类型系统中具有特殊含义,或者因为它们不能被继承,这些类型作为约束是无效的。
- 删除重复约束(CS0405)。 每个约束只能在约束子句中出现一次。 如果有
where T : I, I,请删除重复项。 - 仅使用非密封类型作为约束(CS0701)。 密封类、结构和枚举都不能被继承,因此将它们用作约束没有任何意义。 使用所需类型实现的接口,或使用非密封基类。
- 不要将特殊类用作约束(CS0702)。 类型 Object、Array 和 ValueType 不能用作约束。 每个类型都已经派生自
Object,所以对其进行约束没有任何意义。Array和ValueType是无法直接继承的抽象基类型。 如果需要类似数组的行为,请使用IList<T>或IEnumerable<T>。 - 确保约束类型至少与泛型类型(CS0703)一样可访问。 公共泛型类型无法使用内部类型的约束,因为外部代码无法提供有效的类型参数。 使约束类型公开,或减少泛型类型的可访问性。
- 仅使用接口、非密封类或类型参数作为约束(CS0706)。 不能将数组、密封类、结构、枚举或其他无效类型用作约束。 请考虑使用由所需类型实现的接口。
- 不要将静态类用作约束(CS0717)。 静态类无法扩展,因为它们仅包含静态成员。 任何类型都不能派生自静态类,使其作为约束是无用的。
- 对类型约束使用符合 CLS 的类型(CS3024)。 当程序集被标记
[assembly: CLSCompliant(true)]时,使用不符合 CLS 的类型作为泛型类型约束可能会导致某些语言编写的代码无法使用泛型类。
有关详细信息,请参阅类型参数的约束。
约束满意度和转换
-
CS0311: 类型不能用作泛型类型或方法中的类型参数
T。没有从“type1”到“type2”的隐式引用转换。 - CS0312:该类型不能用作泛型类型或方法的类型参数。可为 null 的类型不满足“constraint”约束。
- CS0313:该类型不能用作泛型类型或方法中的类型参数。可为空类型不满足“constraint”约束。可为空类型不能满足任何接口约束。
- CS0314:该类型不能用作泛型类型或泛型方法中的类型参数。不存在从“type”到“constraint”的装箱转换或类型参数转换。
-
CS0315:该类型不能用作泛型类型或方法的类型参数
T。不存在从“type”到“constraint”的装箱转换。 - CS0452: 类型“type name”必须是引用类型,才能将其用作泛型类型或方法“generic”中的参数“参数名称”。
- CS0453: 类型“type name”必须是不可为 null 的值类型,才能将其用作泛型类型或方法“generic”中的参数“参数名称”。
- CS8377:类型“type”及其在任意嵌套级别中的所有字段都必须是不可为 null 的值类型,才能将其用作泛型类型或方法“generic”中的参数“parameter”。
当类型参数不满足泛型类型参数声明的约束时,会发生这些错误。 类型参数必须具有正确的转换、继承关系和结构属性才能匹配所有约束。
- 将类型参数更改为具有对约束类型(CS0311)的隐式引用转换的类型参数。 当类型参数具有类似
where T : BaseType约束时,任何类型参数都必须通过隐式引用转换或标识转换转换为BaseType。 隐式数值转换(如 fromshorttoint)不满足泛型类型参数约束。 - 使用不可为 null 的值类型或更改约束类型(CS0312、 CS0313)。 可为 Null 的值类型(例如
int?)不同于其基础值类型,并且不满足相同的约束。 可空值类型无法满足接口约束,因为可空包装类型本身并未实现该接口。 将该值类型的非可空形式用作类型参数。 - 在任何派生类声明(CS0314)中重复基类的类型参数约束。 当派生泛型类从受约束基泛型类继承时,派生类必须对其相应的类型参数声明相同的约束。
- 确保类型参数满足引用类型或类约束(CS0315)。 当类型参数约束为类类型时,不能使用值类型(结构体)作为类型实参,因为不存在满足该约束关系的装箱转换。 使用继承自或实现约束的引用类型。
- 指定约束时
class,使用引用类型作为类型参数(CS0452)。 值类型(例如struct或int不能满足class约束)。 将类型参数更改为引用类型,或者如果泛型类型可以使用值类型,则删除class约束。 - 指定了
struct约束时,请使用不可为 null 的值类型作为类型参数(CS0453)。 引用类型、可为 null 的值类型(int?)和其他非值类型无法满足struct约束。 使用具体的不可为 null 的值类型,例如int,double或用户定义的struct。 - 指定
unmanaged约束时,请使用其所有字段均为非托管类型的类型(CS8377)。 该unmanaged约束要求使用不可为 null 的值类型,并且在每一层嵌套中,每个字段也都必须是非托管类型。 包含引用类型字段或未确认为非托管类型的泛型类型参数的类型,不满足此约束。
有关详细信息,请参阅类型参数的约束。
约束冲突和循环依赖项
- CS0454: 涉及类型参数 1 和类型参数 2 的循环约束依赖项。
- CS0455: 类型参数继承冲突约束“constraint1”和“constraint2”。
- CS0456: 类型参数“type parameter 1”具有“结构”约束,因此“type parameter 1”不能用作“type parameter 2”的约束。
- CS8379: 类型参数“type parameter 1”具有“非托管”约束,因此“类型参数 1”不能用作“类型参数 2”的约束。
约束无法创建循环依赖项,类型参数无法同时继承无法同时满足的冲突约束。 值类型约束(struct 和 unmanaged)是隐式密封的,因此不能将其用作其他类型参数的约束。
- 删除循环约束依赖项(CS0454)。 类型参数不能直接或间接地通过其约束依赖于自身。 例如,
where T : U where U : T创建循环依赖项。 通过删除其中一个约束来中断周期。 - 删除冲突继承的约束(CS0455)。 类型参数不能限制为多个不相关的类,因为 C# 不支持多个类继承。 同样,它不能同时约束为
struct和类类型。 重构类型层次结构或删除其中一个冲突约束。 - 不要将受
struct或unmanaged约束的类型参数用作另一个类型参数的约束(CS0456、CS8379)。 值类型约束是隐式密封的,因此其他类型无法派生自它们。 若要解决此错误,请将值类型或非托管约束直接放在第二个类型参数上,而不是通过第一个类型参数间接约束它。
有关详细信息,请参阅类型参数的约束。
替代和实现约束规则
- CS8665: 方法“method”为类型参数“type parameter”指定了“class”约束,但被重写或显式实现的方法“method”的对应类型参数“type parameter”不是引用类型。
- CS8666:方法“method”为类型参数“type parameter”指定了“struct”约束,但被重写或显式实现的方法“method”的对应类型参数“type parameter”并非不可为 null 的值类型。
- CS8822:方法“method”为类型参数“type parameter”指定了“default”约束,但被重写或显式实现的方法“method”的相应类型参数“type parameter”具有引用类型约束或值类型约束。
- CS8823: “默认”约束仅在重写和显式接口实现方法上有效。
重写虚拟方法或显式实现接口方法时,重写方法的类型参数的约束必须与基方法的约束兼容。
default 约束是一种特殊修饰符,仅用于重写和显式接口实现的情况下,用于指示某个类型参数既不具有 class 约束,也不具有 struct 约束。
- 确保重写方法的约束条件与基类方法的约束条件匹配(CS8665、CS8666)。 如果基方法的相应类型参数不受引用类型约束,重写将无法添加
class约束。 同样,如果基方法的类型参数不受值类型约束,则它不能添加struct约束。 重写必须与基本声明兼容。 -
default仅在基方法的类型参数不受约束(CS8822)时才使用约束。 该default约束指示类型参数没有class或struct约束。 如果被重写方法的对应类型参数已具有class或struct约束,则不能应用default。 - 仅在重写方法或显式接口实现方法上使用
default约束(CS8823)。 约束default对常规方法声明无效。 它专门用于在重写某个方法时消除歧义:如果基类中的该方法具有不受约束的类型参数,而你又需要表明重写后的方法也保持该类型参数不受约束。
有关详细信息,请参阅 类型参数的约束 和 default 约束。
构造函数约束
-
CS0304: 无法创建变量类型的实例,因为它没有
new()约束。 - CS0310: 类型必须是具有公共无参数构造函数的非抽象类型,才能将其用作泛型类型或方法中的参数。
- CS0417: 标识符:创建变量类型的实例时无法提供参数。
这些错误与 new() 约束以及使用 new 运算符实例化类型参数有关。
- 将
new()约束添加到需要实例化的类型参数(CS0304)。 在泛型类型或方法中使用new T()时,编译器必须确保任何类型参数都有无参数构造函数。 该new()约束提供此保证。 - 确保类型参数具有公共无参数构造函数(CS0310)。 当类型参数具有
new()约束时,用作类型参数的任何具体类型必须是非抽象的,并且必须提供公共无参数构造函数。 仅具有专用、受保护或参数化构造函数的类型不能满足new()约束。 - 实例化类型参数时删除构造函数参数(CS0417)。 约束
new()仅保证无参数构造函数。 不能将参数new T(arguments)传递给 。 如果需要使用特定参数构造实例,请考虑使用工厂模式或定义构造行为的接口约束。
有关详细信息,请参阅 类型参数的约束 和 new() 约束。
类型参数数量与用法
- CS0224: 具有 vararg 的方法不能为泛型、处于泛型类型或具有参数参数。
- CS0305: 使用泛型类型需要 N 类型参数。
- CS0306: 类型不能用作类型参数。
- CS0307: “标识符”不能与类型参数一起使用。
- CS0308: 非泛型类型或方法不能与类型参数一起使用。
- CS7002: 意外使用泛型名称。
- CS8389:当前 上下文中不允许省略类型参数。
这些错误与向泛型类型和方法提供正确的参数数和类型有关。
- 从使用
__arglist(CS0224) 的方法中删除泛型类型参数或包含泛型类型声明。 关键字__arglist与泛型不兼容,因为处理变量参数列表的运行时机制与泛型类型参数所需的类型替换冲突。 - 提供泛型声明(CS0305)中指定的类型参数的确切数量。 定义中的每个泛型类型参数在实例化泛型类型时必须具有相应的类型参数。
- 仅将有效类型用作类型参数(CS0306)。 指针类型(如
int*或char*)不能用作类型参数,因为泛型类型需要垃圾回收器可以跟踪的托管类型。 - 从非泛型构造中删除类型参数语法(CS0307、 CS0308)。 括在尖括号中的类型参数只能应用于声明类型参数的泛型类型和方法。 确保导入了包含该类型的泛型版本的命名空间。
- 从不支持泛型的声明中删除类型参数(CS7002)。 某些构造(如枚举)不能为泛型。 如果需要枚举值的泛型容器,请考虑改用泛型类或结构。
- 显式提供所有必需的类型参数(CS8389)。 在某些上下文中,例如使用
typeof运算符或创建委托,必须提供所有类型参数,并且不能省略它们。 例如,使用typeof(List<int>)而不是尝试省略类型参数。
类型参数推理
- CS0411: 无法从用法推断方法“method”的类型参数。请尝试显式指定类型参数。
如果在未显式提供类型参数的情况下调用泛型方法,并且编译器无法推断你打算使用哪种类型参数,则会发生此错误。 编译器从在调用站点传递的方法参数的类型推断类型参数。
- 在尖括号(CS0411)中显式指定类型参数。 如果编译器无法从方法参数中确定类型参数,请直接提供它们。 例如,将
G()更改为G<int>()。 这种错误通常发生在以下情况:泛型方法没有可供推断类型的参数,或者传递了null参数而编译器无法确定预期的类型。
有关详细信息,请参阅 泛型方法。
类型参数差异
- CS1960: 差异修饰符无效。只能将接口和委托类型参数指定为变体。
- CS1961:变体无效:类型参数对于 'type' 必须是协变有效的。类型参数是逆变的。
- CS8427: 不能在具有“in”或“out”类型参数的接口中声明枚举、类和结构。
方差修饰符(in 表示逆变,out 表示协变)用于控制在接口和委托声明中如何使用类型参数。 只有接口和委托支持变体。 协变(out) 类型参数只能出现在输出位置(返回类型),而逆变类型in参数只能出现在输入位置(参数类型)。
- 仅在接口和委托类型参数上使用方差修饰符(CS1960)。 类、结构和其他类型声明不支持变体修饰符。 只有
interface和delegate声明才能在其类型参数上使用in或out。 - 对于仅出现在返回类型中的类型参数,请使用
out(协变);对于仅出现在参数类型中的类型参数,请使用in(逆变)(CS1961)。 如果类型参数必须同时出现在输入和输出位置,请删除方差修饰符。 - 不要在变体接口(CS8427)内声明枚举、类或结构。 不允许在具有
in或out类型参数的接口内嵌套类型声明,因为它们可能违反差异安全规则。 将嵌套类型移到接口声明之外。
有关详细信息,请参阅 泛型中的协变和逆变。
泛型类型使用限制
-
CS0403: 无法将 null 转换为类型参数,因为它可能是不可为 null 的值类型。请考虑改用
default(T)。 -
CS0413: 类型参数不能与运算符一起使用
as,因为它没有类类型约束,也没有class约束。 - CS0695: “type”不能同时实现“interface1”和“interface2”,因为它们可能会统一某些类型参数替换。
- CS0698: 泛型类型无法从类型派生,因为它是属性类。
- CS0704: 无法在“type”中执行非虚拟成员查找,因为它是类型参数。
- CS0718: “type”:静态类型不能用作类型参数。
- CS1720: 表达式始终会导致 System.NullReferenceException,因为“泛型类型”的默认值为 null。
- CS1763: “parameter”的类型为“type”。字符串以外的引用类型的默认参数值只能使用 null 进行初始化。
- CS8322: 无法将具有动态类型的参数传递给具有推断类型参数的泛型本地函数。
- CS9338:可访问性不一致:类型的可访问性比类低。
这些错误与泛型类型和类型参数如何在表达式、继承和成员访问中使用的限制有关。
- 将分配替换为
nulldefault(T)或添加class约束(CS0403)。 当分配给null不受约束的类型参数时,编译器无法保证类型参数是引用类型。 使用default(T),它为任何类型提供适当的默认值,或添加class约束(如果特别需要引用类型语义)。 - 使用
class运算符时添加as或指定的类型约束(CS0413)。 如果转换失败,as运算符将返回null,但值类型不能为null。class添加约束以确保类型参数始终是引用类型。 - 避免多次使用可以统一的类型参数实现同一泛型接口(CS0695)。 当类使用不同类型参数(例如
class G<T1, T2> : I<T1>, I<T2>)多次实现泛型接口时,使用两个参数的相同类型实例化将产生冲突。 仅实现一次接口,或重新构造以防止统一。 - 从属性类中删除泛型类型参数(CS0698)。 此错误不再在 C# 的当前版本中生成,因为现在支持泛型属性。
- 使用具体约束类型,而不是嵌套成员访问的类型参数(CS0704)。 无法通过类型参数访问嵌套类型或非虚拟成员。 请勿使用
T.InnerType,而应直接使用已知的约束类型,例如BaseClass.InnerType。 - 不要将静态类型用作类型参数(CS0718)。 静态类型无法实例化,不能用作泛型参数。 从泛型参数中删除静态类型。
- 当
T被约束为引用类型时,避免在default(T)上调用实例成员(CS1720)。 当T具有class约束时,default(T)是null,因此对其调用实例成员始终会引发 NullReferenceException。 在调用成员之前添加 null 检查,或重构代码以避免直接使用default(T)。 - 将
null用作类型为引用类型的可选参数的默认值(CS1763)。 如果泛型方法具有类型T参数并且T是引用类型,请替换为default(U)null因为可选参数默认值必须是编译时常量,并且default(T)不能修复该要求。 - 将动态值传递给泛型本地函数时显式指定类型参数(CS8322)。 将参数传递给
dynamic泛型本地函数时,编译器无法推断类型参数。 显式指定类型参数,或将动态值强制转换。 - 确保公共签名或受保护签名中使用的类型参数至少与成员(CS9338)一样可访问。 公共泛型成员必须使用可公开访问的类型参数。 将类型参数公开,或减少成员的可访问性。
UnmanagedCallersOnly 限制
- CS8893: “type”不是“UnmanagedCallersOnly”的有效调用约定类型。
- CS8894: 不能对具有“UnmanagedCallersOnly”特性的方法使用“type”作为参数或返回类型。
- CS8895: 使用“UnmanagedCallersOnly”属性的方法不能具有泛型类型参数,也不能在泛型类型中声明。
- CS8896: “UnmanagedCallersOnly”只能应用于普通静态非抽象、非虚拟方法或静态本地函数。
属性 UnmanagedCallersOnlyAttribute 标记非托管代码可以调用的方法。 这些方法具有严格的要求,因为运行时必须处理托管和非托管调用约定之间的转换。
- 仅在属性(
UnmanagedCallersOnly)中使用有效的调用约定类型。 该特性的CallConvs属性仅接受来自System.Runtime.CompilerServices命名空间的已识别调用约定类型。 - 仅使用 blittable 类型 作为参数类型和返回类型(CS8894)。 标记
UnmanagedCallersOnly的方法不能使用托管类型(如string或object)作为参数或返回类型,因为非托管调用方无法管理垃圾回收的引用。 - 从
UnmanagedCallersOnly方法中删除泛型类型参数,不要在泛型类型(CS8895)中声明它们。 非托管调用约定不支持泛型,因为运行时无法确定泛型类型替换的正确调用约定。 - 仅适用于
UnmanagedCallersOnly普通静态、非抽象、非虚拟方法或静态本地函数(CS8896)。 无法标记UnmanagedCallersOnly实例方法、抽象方法和虚拟方法,因为非托管调用方无法执行这些方法所需的调度机制。
有关详细信息,请参阅 UnmanagedCallersOnlyAttribute。