【发布时间】:2020-04-18 19:55:05
【问题描述】:
在阅读了 HNQ 上的 this question 之后,我继续阅读了有关 Nullable Reference Types in C# 8 的内容,并做了一些实验。
我非常清楚,当有人说“我发现编译器错误!”时,有 10 次中有 9 次,甚至更多次。这其实是故意的,和自己的误解。而且由于我今天才开始研究这个功能,显然我对它的理解不是很好。顺便说一句,让我们看看这段代码:
#nullable enable
class Program
{
static void Main()
{
var s = "";
var b = s == null; // If you comment this line out, the warning on the line below disappears
var i = s.Length; // warning CS8602: Dereference of a possibly null reference
}
}
阅读我上面链接的文档后,我希望s == null 行会给我一个警告——毕竟s 显然不可为空,因此将其与null 进行比较是没有意义的。
相反,我在 next 行收到警告,警告说 s 可能是空引用,尽管对于人类来说,显然不是。
此外,如果我们不将s 与null 进行比较,警告将不显示。
我做了一些谷歌搜索,然后点击了a GitHub issue,结果证明这完全是关于其他事情,但在此过程中,我与一位贡献者进行了对话,他对这种行为有了更多的了解(例如 “Null检查通常是告诉编译器重置其先前关于变量可空性的推断的有用方法。”)。然而,这仍然让我的主要问题没有得到解答。
我没有创建一个新的 GitHub 问题并可能占用非常忙碌的项目贡献者的时间,而是将其发布给社区。p>
能否请您解释一下发生了什么以及为什么?特别是,为什么在s == null 行上没有生成警告,为什么我们有CS8602,而null 在这里似乎不可能引用?如果可空性推断不是万无一失的,正如链接的 GitHub 线程所暗示的那样,它怎么会出错?有什么例子?
【问题讨论】:
-
似乎编译器本身设置了此时变量“s”可能为空的行为。无论如何,如果我曾经使用过字符串或对象,那么在调用函数之前应该始终进行检查。 "s?.Length" 应该可以解决问题,并且警告本身应该消失。
-
@chg,应该不需要
?,因为s不能为空。它不会变成可以为空的,仅仅是因为我们愚蠢到将它与null进行比较。 -
我在关注一个较早的问题(抱歉,找不到它),其中假设如果您添加一个值是否为空的检查,那么编译器会将其视为“提示”值可能为空,即使事实证明并非如此。
-
@stuartd,是的,看起来就是这样。所以现在的问题是:为什么这有用?
-
@chg,好吧,这就是我在问题正文中所说的,不是吗?
标签: c# roslyn c#-8.0 nullable-reference-types