C# 8 在返回具有可空约束的可空泛型时发出警告

C# 8 gives a warning when returning a nullable generic with nullable constraint

此代码:

public T Foo<T>()
    where T : class?
{
    return null;
}

给出以下错误:

A null literal introduces a null value when 'T' is a non-nullable reference type

当我们说 T 可以为空时,我不明白为什么我们不能 return null。如果我们另外尝试 return T? 我们将得到一个错误,即 T 必须是不可空的。

似乎不​​可能同时具有可空约束和 return 可空结果。

假设你打电话给:

string result = Foo<string>();

result 现在包含 null。但它是一个 string,不可为空。

编译器警告您 Foo<T> 可能会在 T 不可为 null 的情况下调用,并且在这种情况下 returning null 将是意外的。

请注意,where T : class? 意味着 T 可能 可以为空,但也可能不是。 stringstring? 都是允许的。我不相信有任何方式可以说“T 必须 可以为空”。


如果你想说:

  1. T 允许为空
  2. T不可为空时,那么这个类型仍然可以returnnull

那你可以这样写:

[return: MaybeNull]
public T Foo<T>()
    where T : class?
{
    return null!;
}

SharpLab

请注意,MaybeNull 仅适用于方法的契约,而不适用于其主体,这就是我们需要 return null! 的原因。但是,您可以在上面的 SharpLab link 中看到调用者 string result = Foo<string>(); 收到了正确的警告。

让我们从基础开始。假设您有一个允许它具有空值的引用类型变量。但是你的程序设计要求它始终不为空,如果遇到空值,它很可能得到 NullReferenceException

为了避免此类设计问题,引入了 NullableReference 类型。意味着如果一个引用类型被允许有 null 你应该将它标记为 Nullable 并且任何用法都应该在使用它之前检查 null 值。如果未找到检查,则编译器将生成警告。

如果您阅读 this introductory article on NullableReferenceTypes,您将清楚了解此新功能的目的。