C# 中使用隐式类型的局部变量时可能会遇到 Nullable 的问题。

4

我已经从这个线程中知道,在.NET 7中,即使将Nullable设置为“Enabled”,隐式声明的引用类型也是可空的,我甚至知道为什么。

我不是在问为什么。我在询问一种解决方法。

在评论中,@shingo指出了一个简单示例的解决方法,因此在这里我将列出带我来到这里的问题:LINQ查询的结果。下面的变量nonEmpty实际上是可空的。

var nonEmpty = myList.Where(s => s.Length > 0).ToList();
nonEmpty = null;  // again valid when it should not be

要使它非空,我必须明确声明类型。

List<string> nonEmpty = myList.Where(s => s.Length > 0).ToList();
nonEmpty = null;  // compiler warning/error as desired.

对于像List<string>这样的短命名类型,这不是问题。但当名称像我的代码中那样非常长时,就会出现问题。

所以我的问题是:

是否有任何简写方法可以让我避免在此处声明类型?或者甚至是未来的语言提案中有这样的技巧吗?

实际上,我尝试了以下3个声明,但都没有成功。只有第三个编译通过。

var! nonEmpty = myList.Where(s => s.Length > 0).ToList();
var nonEmpty! = myList.Where(s => s.Length > 0).ToList();
var nonEmpty = myList.Where(s => s.Length > 0).ToList()!

是的,我是。我链接的那个项目描述了这显然是C#语言设计者的一个刻意决定。我甚至新建了一个启用了可空类型的测试项目,并添加了那一行代码,发现效果一样。如果你这样做,并将鼠标悬停在列表变量上方,你会发现它被Intellisense列为可空类型。我也不敢相信。 - Joe
1
这里是否有一个实际的问题需要解决呢?重新分配变量的简单解决方案是“那就不要那样做”。尽管var隐式为空,但静态分析将在整个方法中将其视为非空,因此除非重新将变量分配为null,否则不会影响可空性分析--如果确实这样做了,它会再次发出警告。您当前唯一没有获得的是如果您分配null,则没有明确的警告,尽管这可能被视为缺点,但我认为真正的问题在于根本不应该重新分配本地变量,因为值是次要的。 - Jeroen Mostert
1
与上述相关:https://github.com/dotnet/csharplang/issues/188。 - Jeroen Mostert
1
我认为你没有理解我的观点:如果有人执行 nonEmpty = null,那么如果随后尝试以需要其不是 null 的方式使用 nonEmpty,他们 收到警告。赋值不会发出警告,但赋值并不是引起问题的原因——可能访问 null 引用才是,而分析仍然会发出警告。或者从哲学上说,如果分配了一个从未被读取的 null,它会发出声音吗?实际上不会。 - Jeroen Mostert
1
空值分析和NRTs的实现确实是微妙的——这是有意为之的,以确保即使最小程度地采用,现有代码也能从中获得价值,并逐渐选择加入。一个简单的固定类型系统,在其中变量永远不可能持有“null”引用,早期被拒绝了,因为它将永远无法获得推广,因为它会太昂贵来适应现有的代码。最终结果在语义层面上有点难以理解和使用,但在很大程度上确实做到了“正确的事情”,这就是它的价值所在。 - Jeroen Mostert
显示剩余6条评论
1个回答

1

这不是一个真正的答案,而更像是一个解决办法,只有在您有多个实例的非空长名称类型时才有用 - 使用using指令来为您的类型设置别名,如下所示:

using strList = System.Collections.Generic.List<string>;

然后你可以在代码中使用strList作为List<string>的别名。 如果你想在项目中的多个文件中使用这个别名,你可以使用global modifier来修改你的using指令,然后在整个项目中使用该别名(需要c# 10或更高版本):

global using strList = System.Collections.Generic.List<string>;

请参考附带的图片作为演示:

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接