65.9K
CodeProject 正在变化。 阅读更多。
Home

C#中的(非)可空引用类型

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.08/5 (6投票s)

2024 年 9 月 22 日

CPOL

3分钟阅读

viewsIcon

5831

这篇文章主要是抱怨一个原本可能很棒的功能,实际上却成了安全漏洞的来源。

背景

在开始之前,我必须说我非常支持编程语言中的安全功能,并且 10 多年前我就为 C# 提出了我所谓的“required”关键字。 然而,我不断看到越来越多的人谈论 C# 中可空引用类型的强大之处,但实际上,我对该功能在语言中的糟糕实现感到非常不满,而这篇文章就是关于这个问题的。

(非)可空引用(类型)

那么,C# 中可空引用类型有三个我不喜欢的地方

  1. 它们与不可为空的变量有关;
  2. 它们不是类型;
  3. 它们可能会使您的代码容易受到攻击。

如果这些简短的描述还不够,让我详细说明每一个

1. 它们与不可为空的变量有关

将新功能称为“可空引用类型”一次犯了两个错误。 在 C#(和 .NET)中,引用始终是可空的。 新功能试图添加的是非可空引用(类型)。 好吧,“类型”部分是第 2 项的内容。

2. 它们不是类型

非可空引用仅存在于变量声明中,包括局部变量、方法参数、返回“类型”(不确定这里使用哪个词最好)和字段。 然而,作为一种类型,它们仍然是完全可空的类型。 尽管在编写它们时,它们看起来可能与可空与非可空值类型相同,但非可空引用仍然使用可空类型,而可空和非可空值类型的实际类型是不同的(例如,Nullable<int>和仅仅是int)。

3. 它们可能会使您的代码容易受到攻击

添加非可空引用的全部目的是避免 null 值进入不应该进入的地方的错误。 然而,(非)可空引用提供的虚假安全性恰恰相反。 许多开发人员(无论是他们自己,因为他们使用的工具,还是他们工作的公司强制执行的实践)都在系统地从他们的代码中删除空值验证,毕竟他们正在使用非可空引用。 不幸的是,非可空引用仍然可以为空,并且如果它们没有得到适当的检查,空值可能会进入不应该允许为空的数据结构中,并导致以后发生错误。 这实际上会将安全漏洞引入到不同模块和线程之间共享的组件中,并使整体调试体验更加困难,这与该功能应该做的事情恰恰相反。

如何才能做得更好?

从概念上讲,非常简单。 非可空引用类型应该是它们自己的类型。 它们应该被视为与其可空对应项不同的类型,可能遵循可空和非可空值类型的相同模式,甚至允许可空和非可空类型之间的重载,并保证 IL 本身永远不允许非可空引用类型实际包含空值,这与 C++ 引用的工作方式非常相似,因为尝试将 nullptr 强制转换为引用将导致立即错误。

结论

这里的结论有两个不同的方向。 首先,非可空引用只是当前实现中的一个半成品功能。 我并不是说你不应该使用它,但要注意它的缺陷。

这引出了第二个结论,即继续验证您的输入值,即使它们不应该是空的,特别是如果您编写了可能在您的项目之外使用的共享库,这些库可能被其他在其自己的项目中不使用非可空引用的开发人员使用。

© . All rights reserved.