【问题标题】:Non-Nullable becomes Nullable on returnNon-Nullable 在返回时变为 Nullable
【发布时间】:2022-02-08 17:34:21
【问题描述】:

我想我在某个地方看到过这个问题的答案,但我找不到它,也不记得答案了。

假设 Nullable-Reference-Types 已启用。

有一个方法返回string。该方法的调用者将结果字符串存储到一个变量中。变量将为 Nullable,即使方法的返回值不可为空。

static string MyMethod() 
{
   return "Hello World!";
}

public static void Main() 
{
   // result is of type string? here. Hence nullable.
   var result = MyMethod();
}

原始类型似乎不会发生同样的情况,但引用类型确实会发生这种情况,例如object。有点违背了 NRT 对我的目的。我敢肯定这是有原因的,而且是“设计使然”。

【问题讨论】:

  • 无法复制。我可以打印出result.Lengthresult2.Length 而没有任何警告。
  • 您如何观察到该变量现在可以为空?也许您在分析和观察这种行为时/无论做什么都存在问题?
  • result 将是 string?,因为使用了 var(这是设计使然,根据 Matthew 的回答),但 result2 肯定不会——它是 string,就像你指定的那样。 result2 = null 不会编译。请注意,尽管有隐式类型,但静态分析会发现 result 在调用 MyMethod 后实际上并不是 null,因此涉及它的表达式不会触发警告。在所有情况下,NRT 仅存在于语言级别,而不是运行时级别,因此底层 reference 始终可以保存null(强制通过result2 = null!)。这也是一种设计选择。
  • 是的,result2 绝对不能为空。我会在我的回答中提到这一点,以使其明确。
  • @JeroenMostert 你是对的result2。它不能为空。可能是静态分析的一个奇怪的挂断......或者只是我。

标签: c# nullable-reference-types


【解决方案1】:

这确实是设计使然。

选择此设计的会议记录在这里:https://github.com/dotnet/csharplang/blob/main/meetings/2019/LDM-2019-12-18.md#var

总结:发现人们经常不得不显式键入变量而不是使用var,因为在从非空返回方法分配之后,代码继续将null 分配给变量。

引用会议记录:

此时,我们已经看到了大量需要人员的代码 拼出类型而不是使用 var,因为代码可能会分配 null 稍后。

也就是说,发现如下代码非常频繁:

var someVariable = SomeMethodThatDoesntReturnNull();
...
someVariable = null; // or someVariable = someMethodThatCanReturnNull();

请注意(正如 Jeroen Mostert 所指出的)您的问题中的result2 不可为空,因为它被明确键入为不可为空。我不确定你为什么认为它可以为空的,但它绝对不是。

例如,查看this repro on DotNetFiddle 并注意第 11 行的警告。

【讨论】:

  • 编辑:更正了设计会议记录的链接。
【解决方案2】:

在 C# 8.0 中,字符串被称为可以为 null 的“字符串!”,因此 Allow Null 注释允许将其设置为 null,即使我们返回的字符串不是 null(例如,我们进行比较检查)如果为 null,则将其设置为默认值。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-01
    • 1970-01-01
    • 2021-09-27
    • 1970-01-01
    相关资源
    最近更新 更多