具有不可为 null 的泛型参数的 C# 泛型方法警告可能存在 null 引用

sti*_*org 4 c# generics nullable nullable-reference-types

今天编程的时候出现了下面的情况。泛型方法接受不可为 null 的泛型参数。该方法基本上只是将通用值插入到集合中。但是,这会产生编译器警告,指示泛型参数可能为空。从表面上看,这似乎是编译器中的一个错误,并且与可为空值的设计相矛盾。然而,我确信有一些我没有看到的很好的解释。

请考虑以下情况的简化示例: public void M1<T>(T t, List<object> l) => l.Add(t); 编译器警告 t 中的 t 可能为 null l.Add(t)

另外,为了完整性,以下方法给出了相同的错误(如预期的那样): public void M1<T>(T? t, List<object> l) => l.Add(t);

有人对此有一些好的见解吗?

can*_*on7 6

有人可以打电话:

var list = new List<object>();
M1<string?>(null, list);
Run Code Online (Sandbox Code Playgroud)

现在,您的列表(应仅包含不可为空的对象)包含null. 因此发出警告。

如果你想防止T成为可空类型,那么:

public void M1<T>(T t, List<object> l) where T : notnull
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

这会向您发出警告:

M1<string?>(null, new List<object>());
^^^^^^^^^^^
// warning CS8714: The type 'string?' cannot be used as type parameter 'T' in the generic 
// type or method 'C.M1<T>(T, List<object>)'. Nullability of type argument 'string?' doesn't
// match 'notnull' constraint.
Run Code Online (Sandbox Code Playgroud)

如果您想让Tbe null,但仍然禁止nullt参数的值,那么:

public void M1<T>([DisallowNull] T t, List<object> l)
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

这会向您发出警告:

M1<string?>(null, new List<object>());
            ^^^^
// warning CS8625: Cannot convert null literal to non-nullable reference type.
Run Code Online (Sandbox Code Playgroud)

当然,如果您想允许,null那么您l需要成为List<object?>.