为什么仍然可以将 null 分配给不可为 null 的引用类型?
Why is it still possible to assign null to non nullable reference type?
我很困惑。
我认为启用 c# 8 和可为空的引用类型会阻止将 null 分配给非可为空的引用类型,但显然这只是编译时的警告,我知道你可以将其强制为错误并停止构建,但我认为这不仅仅是编译器检查。
看看这个例子
https://dotnetfiddle.net/4eCs5L
如果您 运行,仍然可以将 null 分配给不可为 null 的引用类型,为什么在 运行 时不抛出错误?
使用此引用 https://docs.microsoft.com/en-us/dotnet/csharp/nullable-references
我可以看到指令
#nullable enable: Sets the nullable annotation context and nullable warning context to enabled
如果您仍然希望它抛出错误,请将其添加到您的项目文件中 <WarningsAsErrors>nullable</WarningsAsErrors>
TLDR:向后兼容性
如果可空引用类型是 C# 1 的一部分,那么 null
对非可空类型的赋值会引发编译错误。
C# 的问题是已经有很多没有 Nullable Reference Types 的现有代码。 null
分配的编译器错误会破坏所有现有代码或库。
您可以在 C# 程序管理器的 .NET 博客 Post 中找到完整的解释:https://devblogs.microsoft.com/dotnet/nullable-reference-types-in-csharp/
该功能的目的是为开发人员提供更多工具来捕获最普遍的错误类型,解除对空引用/指针的引用,从而导致应用程序崩溃。
因此,C# 设计团队添加了“可空引用类型”,具有足够的语法,开发人员可以更清楚地声明代码的意图和要求。
新语法可以表达的东西:
- 允许 NULL 或不允许 NULL 的属性和字段
- 方法参数可以为NULL,或者应该为NULL
- 方法 return 可以为 NULL 或不会为 NULL 的值
启用后,编译器将使用这种新语法、属性和其他元数据,在发现不“保证”正确的代码时开始发出警告。换句话说,如果你读到一个 属性 说它可以 return NULL,并尝试将它作为参数值传递给方法说参数不应该为 NULL,你会收到警告。
您可以在项目上使用现有指令,将某些警告作为错误处理,并中断构建,这包括这些新警告。
但是,他们没有添加的是 运行时间检查。如果您说参数值永远不应该为 NULL,并且忽略警告或绕过它(有很多方法可以说“相信我,这是正确的”),那么该方法将 运行 如前所述。没有不可见的 if 语句或 guard 语句来验证参数不为 null。
基本上,您仍然应该添加这样的 if 语句。
与您的看法相反,这正是他们设计此功能的目的。他们没有忘记添加这些 运行 时间检查,他们故意没有添加它们。
例如,如果您通过反射调用方法,编译器不会参与,因为它是 运行time 事情,因此根本不会执行任何检查。如果该方法没有这样的保护语句,它可能稍后会因 NullReferenceException 而崩溃。
我很困惑。 我认为启用 c# 8 和可为空的引用类型会阻止将 null 分配给非可为空的引用类型,但显然这只是编译时的警告,我知道你可以将其强制为错误并停止构建,但我认为这不仅仅是编译器检查。
看看这个例子 https://dotnetfiddle.net/4eCs5L
如果您 运行,仍然可以将 null 分配给不可为 null 的引用类型,为什么在 运行 时不抛出错误?
使用此引用 https://docs.microsoft.com/en-us/dotnet/csharp/nullable-references
我可以看到指令
#nullable enable: Sets the nullable annotation context and nullable warning context to enabled
如果您仍然希望它抛出错误,请将其添加到您的项目文件中 <WarningsAsErrors>nullable</WarningsAsErrors>
TLDR:向后兼容性
如果可空引用类型是 C# 1 的一部分,那么 null
对非可空类型的赋值会引发编译错误。
C# 的问题是已经有很多没有 Nullable Reference Types 的现有代码。 null
分配的编译器错误会破坏所有现有代码或库。
您可以在 C# 程序管理器的 .NET 博客 Post 中找到完整的解释:https://devblogs.microsoft.com/dotnet/nullable-reference-types-in-csharp/
该功能的目的是为开发人员提供更多工具来捕获最普遍的错误类型,解除对空引用/指针的引用,从而导致应用程序崩溃。
因此,C# 设计团队添加了“可空引用类型”,具有足够的语法,开发人员可以更清楚地声明代码的意图和要求。
新语法可以表达的东西:
- 允许 NULL 或不允许 NULL 的属性和字段
- 方法参数可以为NULL,或者应该为NULL
- 方法 return 可以为 NULL 或不会为 NULL 的值
启用后,编译器将使用这种新语法、属性和其他元数据,在发现不“保证”正确的代码时开始发出警告。换句话说,如果你读到一个 属性 说它可以 return NULL,并尝试将它作为参数值传递给方法说参数不应该为 NULL,你会收到警告。
您可以在项目上使用现有指令,将某些警告作为错误处理,并中断构建,这包括这些新警告。
但是,他们没有添加的是 运行时间检查。如果您说参数值永远不应该为 NULL,并且忽略警告或绕过它(有很多方法可以说“相信我,这是正确的”),那么该方法将 运行 如前所述。没有不可见的 if 语句或 guard 语句来验证参数不为 null。
基本上,您仍然应该添加这样的 if 语句。
与您的看法相反,这正是他们设计此功能的目的。他们没有忘记添加这些 运行 时间检查,他们故意没有添加它们。
例如,如果您通过反射调用方法,编译器不会参与,因为它是 运行time 事情,因此根本不会执行任何检查。如果该方法没有这样的保护语句,它可能稍后会因 NullReferenceException 而崩溃。