【问题标题】:C# 8 gives a warning when returning a nullable generic with nullable constraintC# 8 在返回具有可空约束的可空泛型时发出警告
【发布时间】:2020-01-07 15:33:26
【问题描述】:

这段代码:

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

给出以下错误:

当 'T' 不可为空时,空字面量会引入空值 引用类型

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

似乎不可能同时拥有一个可为空的约束并返回一个可为空的结果。

【问题讨论】:

  • 您希望多久发布一次完全相同的问题?见stackoverflow.com/questions/59631254/…stackoverflow.com/questions/59630532/…
  • 虽然看起来像这样,但这并不是同一个问题
  • 嗯,我已经回答了this 有一个已知的issue 有这个约束
  • @PavelAnikhouski,在某种程度上。 github上的这些问题并没有真正的答案。而且我想知道如何使用可空约束返回可空,这似乎是不可能的
  • 显然,在当前的实现中,由于提到的错误,它根本不可能。当然 github 上没有答案,因为那个 bug 没有解决。那么你对这里有什么期望呢?

标签: c# generics nullable-reference-types


【解决方案1】:

想象一下你打电话:

string result = Foo<string>();

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

编译器警告您,Foo&lt;T&gt; 可能会在 T 不可为空的情况下被调用,并且在这种情况下返回 null 是出乎意料的。

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


如果你想说:

  1. T 允许为空
  2. T不可为空时,该类型仍然可以返回null

然后你可以写:

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

SharpLab

注意MaybeNull只适用于方法的契约而不是它的主体,什么时候我们需要返回null!。但是,您可以在上面的 SharpLab 链接中看到调用者 string result = Foo&lt;string&gt;(); 收到了正确的警告。

【讨论】:

  • 好吧,既然我们说class?string 不是string?,我们不应该收到警告吗
  • @IlyaChernomordik No. where T : class? 表示“T 必须是一个类,并且可能可以为空”。这意味着T 可以是例如stringstring?。如果你说where T : class,那么T就不能是string?
  • 感谢您的回答,我现在知道了。 '班级?'表示它可以为空,但不一定为空
【解决方案2】:

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

为避免此类设计问题,引入了NullableReference 类型。表示如果允许引用类型为 null,则应将其标记为 Nullable,并且任何用法都应在使用前检查 null 值。如果未找到检查,则编译器将生成警告。

如果您阅读this introductory article on NullableReferenceTypes,您将大致了解此新功能的意图。

【讨论】:

  • 您好,谢谢您的回答。我得到的全部困惑是因为我认为class? 意味着它必须可以为空。因此,当它明确意味着可以为空时,这一切都是有道理的
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-02
  • 2020-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多