为什么仍然可以将 null 分配给不可为 null 的引用类型?

Moc*_*cas 5 c#-8.0 nullable-reference-types

我很迷惑。我认为启用 c# 8 和可为空的引用类型将阻止将 null 分配给不可为空的引用类型,但显然这只是编译时的警告,我知道您可以将其强制为错误并停止构建,但我认为这不仅仅是编译器检查。

看这个例子 https://dotnetfiddle.net/4eCs5L

如果运行,仍然可以将 null 分配给不可为 null 的引用类型,为什么在运行时不会抛出错误?

Chr*_*eld 11

TLDR:向后兼容性

如果可为空引用类型是 C# 1 的一部分,则null对不可为空类型的赋值将引发编译错误。

C# 的问题是已经有很多现有代码没有可空引用类型。分配时的编译器错误null会破坏所有现有代码或库。

您可以在 C# 程序管理器的 .NET 博客文章中找到完整的说明: https: //devblogs.microsoft.com/dotnet/nullable-reference-types-in-csharp/

  • 它仍然是启用它的一个选项。如果它破坏了所有现有代码,则不要启用它。 (5认同)

ang*_*son 6

该功能的目的是为开发人员提供更多工具来捕获最常见的错误类型,取消引用空引用/指针,从而导致应用程序崩溃。

因此,C# 设计团队添加了“可空引用类型”,并具有足够的语法,使开发人员可以更清楚地声明代码的意图和要求。

新语法可以表达的东西:

  • 允许 NULL 或不允许 NULL 的属性和字段
  • 方法参数可以为 NULL,或者应该为 NULL
  • 方法返回值可以为 NULL,也可以不为 NULL

启用后,编译器将使用这种新语法、属性和其他元数据,在看到不“保证”正确的代码时开始发出警告。换句话说,如果您读取一个可以返回 NULL 的属性,并尝试将其作为参数值传递,而该方法表明该参数不应为 NULL,您将收到警告。

您可以使用项目上的现有指令,指定某些警告应作为错误处理,并中断构建,这包括这些新警告。

然而,他们没有添加运行时检查。如果您说参数值永远不应该为 NULL,并且忽略警告或绕过它(有多种方法可以说“相信我,这是正确的”),那么该方法将按规定运行。没有不可见的 if 语句或保护语句来验证参数不为空。

基本上,您仍然应该添加这样的 if 语句。

与您的看法相反,这正是他们设计该功能的目的。他们没有忘记添加这些运行时检查,而是故意不添加它们。

例如,如果您通过反射调用方法,则编译器不会参与,因为它是运行时的事情,因此根本不会执行任何检查。如果该方法没有此类保护语句,则稍后可能会因 NullReferenceException 而崩溃。