假设我们有一些带有两个参数的泛型方法:
private void TestConstraints<TKey>(TKey key, TKey? nullableKey)
where TKey : notnull { }从.NET6的角度来看,这是非常好的,在这里添加了不可空的引用类型。但是使用尝试是失败的,原因是CS8714类型不能用作参数:
private void TestMethod()
{
var id = 5;
int? nullableId = null;
TestConstraints(id, nullableId);
}警告CS8714类型为'int?‘不能用作泛型类型或方法TestClass.TestConstraints(TKey,TKey?)中的类型参数“TKey”。类型参数'int?‘的空性不匹配“notnull”约束。
显式地将类型指定为int无助。
有人能澄清我是否可以以这种方式操作(将输入参数定义为TKey?),在文档中说明它的位置?
编译器版本:
Microsoft (R)构建引擎版本17.2.0+41abc5629
发布于 2022-07-08 13:14:16
对于不受约束(既不对struct也不对class)的泛型类型参数,对于值类型和引用类型,T - T?的处理方式不同。来自文档
T的类型参数是引用类型,则T?引用相应的可空引用类型。例如,如果T是string,那么T?就是string?。T T? 的类型参数是值类型,则 T?引用相同的值类型 T**.例如,如果** T 是 int**.**,那么** T? 也是int**.**T的类型参数是可空引用类型,则T?引用相同的可空引用类型。例如,如果T是string?,那么T?也是string?。T 的类型参数是可空值类型,则 T? 引用相同的可空值类型。例如,如果T int?**,是 int?**.**,那么** T? 也是int?**.**这部分是由于可空引用和可空值类型的处理方式不同,导致可空值类型实际上是单独的类型- Nullable。
对于TestConstraints,让我们假设T是int,然后根据规则,签名变成TestConstraints<int>(int key, int nullableKey),显然由于类型不匹配而不会为TestConstraints<int>(id, nullableId)调用编译(TestConstraints<int>(id, nullableId.Value)将编译,但在运行时抛出)。
对于int? (Nullable<int>),签名变成TestConstraints<int?>(int? key, int? nullableKey),它将编译(由于隐式转换T -> Nullable<T>),但显然会导致泛型约束失败。
解决方法可以是引入两个重载,一个用于struct,一个用于class,并让编译器弄清楚
private void TestConstraints<TKey>(TKey key, TKey? nullableKey)
where TKey : struct
{ }
private void TestConstraints<TKey>(TKey key, TKey? nullableKey)
where TKey : class
{ }https://stackoverflow.com/questions/72911604
复制相似问题