没有NULL我们会做什么?

Ear*_*rlz 20 language-agnostic null language-design non-nullable

我曾经读过,拥有可空类型是一种绝对的邪恶.我相信这是由创建它们的人写的一篇文章(在Ada中?)我相信这是文章

无论如何,那么如果默认情况下像C#这样的语言使用非可空类型呢?你会如何替换C#或Ruby中的一些常用习语或任何其他null可接受值的常用语言?

Ric*_*erg 26

我认为,大多数语言都将可空性嫁接到各种类型上,而这两种概念应该是正交的,而不是直接宣称可以为空的类型是邪恶的.

例如,所有非原始Java类型(以及所有C#引用类型)都可以为空.为什么?我们可以来回走动,但最终我敢打赌答案归结为"很容易".Java语言没有任何内在要求广泛的可空性.C++参考提供了一个很好的例子,说明如何在编译器级别驱除空值.当然,C++有一些非常丑陋的语法,而Java明确地试图缩减它,所以一些好的功能最终会出现在切割底线上.

C#2.0中的可空值类型向正确的方向迈出了一步 - 将可空性与无关类型语义分离,或者更糟糕的是,CLR实现细节 - 但它仍然缺少与引用类型相反的方法.(代码合同很棒,但它们并没有像我们在这里讨论的那样嵌入到类型系统中.)

大量功能性或其他模糊语言从一开始就使这些概念"直接"......但如果它们被广泛使用,我们就不会进行这种讨论......

要回答你的问题:禁止现代语言中的空白批发,就像所谓的"十亿美元错误"一样愚蠢.有一些有效的编程结构,其中空值很好:可选参数,任何类型的默认/回退计算,其中coalesce运算符导致简洁代码,与关系数据库的交互等.强制自己使用sentinel值,NaN等将是比疾病更糟糕的"治愈".

也就是说,我暂时会同意引文中表达的观点,只要我可以详细说明以适合我自己的经验:

  1. 需要空值的情况比大多数人想象的要小
  2. 一旦你将空值引入库或代码路径中,除了添加它们之外,要摆脱它们困难得多.(所以不要让初级程序员一时兴起!)
  3. 可空的bug以可变的生命周期进行扩展
  4. 与#3相关:早期崩溃

  • 在没有很好的方法来定义可选参数的语言中,您可能(或者您可能不会,取决于您想要的创意)需要NULL.但通常,NULL不是实现可选参数所必需的. (3认同)

bca*_*cat 23

我们在(非常)少数地方使用选项类型,其中允许实际需要空值,并且我们有更少的模糊错误,因为任何对象引用都将保证指向适当类型的有效实例.

  • @Gabe选项类型是可以为空的类型.但是,具有不同类型的语言通常具有类型不可为空的属性.某些类型(例如float或list)可能在其域中内置了null类型.选项类型为我们提供了一种将可空性引入需要的其他类型的方法.问题不在于存在可空性; 它无处不在.如果您构建的语言不可为空,则选项类型允许您在适当的时候重新引入可空性. (6认同)
  • @Gabe选项类型与可空类型不同,因为编译器在不先检查null的情况下不允许使用该值.在F#中,它看起来像`match opt with | 一些(值) - > do_something_with值| 无 - > oops_its_null`.如果您尝试执行`do_something_with opt`,则会出现编译时类型错误. (5认同)
  • 这是正确的答案.这是对SO投票人口的悲伤评论,它没有获得更多的投票. (4认同)
  • @Gabe:选项类型和可空类型之间存在一些差异.一个是你可以有一个选项选项(即一个值为None,Some(None)和Some(x)的类型),这在具有参数多态的语言中尤为重要.另一个不同之处在于,学习(对于程序员)或实现(对于实现者)来说,这是一个较少的概念:选项只是众多数据结构中的一个(0或1 x),如list(任意数量的x顺序),数组(某个固定数量的x),对(x和ay),... (3认同)
  • 不是.只是默认值为_not_以允许null,并且在需要的情况下明确表示允许null. (2认同)

gdj*_*gdj 7

Haskell是一种强大的语言,没有无效的概念.基本上,每个变量必须初始化为非空值.如果要表示"可选"变量(变量可能有值但可能没有),则可以使用特殊的"Maybe"类型.

在Haskell中实现这个系统比在C#中更容易,因为数据在Haskell中是不可变的,因此拥有一个稍后填充的空引用并没有多大意义.但是,在C#中,链接列表中的最后一个链接可能具有指向下一个链接的空指针,该链接在列表展开时填充.我不知道没有null类型的过程语言会是什么样子.

此外,请注意上面的许多人似乎建议用特定于类型的逻辑"无"值(999-999-9999," NULL "等)替换空值.这些值并没有真正解决任何问题,因为人们对空值的问题在于它们是一种特殊情况,但人们忘记了为特殊情况编码.对于特定于类型的逻辑无关值,人们仍然忘记为特殊情况编写代码,但他们避免了捕获此错误的错误,这是一件坏事.