首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如果null不好,为什么现代语言要实现它呢?

如果null不好,为什么现代语言要实现它呢?
EN

Software Engineering用户
提问于 2014-05-02 12:19:11
回答 8查看 52.3K关注 0票数 91

我确信,像Java或C#这样的语言的设计者知道与空引用的存在相关的问题(参见空引用真的是一件坏事吗?)。另外,实现选项类型并不比空引用复杂得多。

他们为什么决定把它包括进去?我确信,缺乏空引用将鼓励(甚至强制)语言创建者和用户提高代码质量(特别是更好的库设计)。

这仅仅是因为保守主义--“其他语言也有,我们也必须拥有它.”?

EN

回答 8

Software Engineering用户

回答已采纳

发布于 2014-05-02 12:38:03

免责声明:由于我个人不认识任何语言设计师,我给你的任何答案都是推测性的。

来自托尼·胡雷本人:

我称它为我的数十亿美元的错误。这是1965年零引用的发明。当时,我正在用面向对象的语言(ALGOL )设计第一个用于引用的综合类型系统。我的目标是确保所有引用的使用都是绝对安全的,由编译器自动执行检查。但我无法抗拒输入空引用的诱惑,因为它很容易实现。这导致了无数的错误、漏洞和系统崩溃,在过去的四十年中,它们可能造成了数十亿美元的痛苦和破坏。

强调我的。

当然,在他看来,这在当时并不是个坏主意。这很可能是因为同样的原因--如果这对图灵奖的发明者来说是个好主意的话,很多人仍然不明白为什么它是邪恶的也就不足为奇了。这也可能在一定程度上是因为新语言与旧语言相似是很方便的,无论是出于营销和学习曲线的原因。例如:

“我们跟踪的是C++程序员,我们设法把他们中的很多人拖到了Lisp的一半。”-Guy Steele,-Guy规范的共同作者

(资料来源:http://www.paulgraham.com/icad.html)

当然,C++有null,因为C有null,没有必要进入C的历史影响。C#某种程度上取代了J++,后者是微软的Java实现,它也取代了C++作为开发C++的首选语言,因此它可以从任何一种语言中获得。

编辑这里还有一段来自Hoare的引文值得考虑:

总体来说,编程语言比过去要复杂得多:面向对象、继承和其他特性仍然没有真正从连贯的、科学的、基于科学的学科或正确性理论的角度来考虑。我最初的假设,作为一名科学家,在我的一生中一直在追求,那就是,一个人把正确性的标准作为一种手段,来聚合到一种体面的编程语言设计上--一种不为其用户设置陷阱的设计,以及一种程序的不同组件与其规范的不同组件明显对应的方法,这样你就可以从总体上对它进行推理。...工具,包括编译器,必须基于某种理论,即编写正确的程序意味着什么。-Oral历史访谈,菲利普L.弗朗萨,2002年7月17日,英国剑桥;查尔斯巴贝奇研究所,明尼苏达大学.[ _http://www.cbi.umn.edu/oh/display.phtml?id=343_](http://www.cbi.umn.edu/oh/display.phtml?id=343%5d)

再强调一下我的。Sun/Oracle和Microsoft是公司,任何公司的底线都是金钱。拥有null对他们的好处可能大于缺点,或者他们可能只是因为时间太紧而无法充分考虑这个问题。作为另一种语言错误的例子,这种错误可能是由于截止日期而发生的:

令人遗憾的是,克隆体被破坏了,但它确实发生了。最初的Java是在紧迫的期限内很快完成的,以满足关闭的市场窗口。最初的Java团队做得非常出色,但并不是所有的API都是完美的。克隆是一个弱点,我认为人们应该意识到它的局限性。-Josh Bloch

(资料来源:http://www.artima.com/intv/bloch13.html)

票数 101
EN

Software Engineering用户

发布于 2014-05-02 21:13:19

我确信像Java或C#这样的语言的设计者知道与空引用的存在相关的问题

当然了。

另外,实现选项类型并不比空引用复杂得多。

我不敢苟同!在C# 2中进入可空值类型的设计考虑是复杂的、有争议的和困难的。他们带领语言和运行时的设计团队进行了长达数月的争论,原型的实现等等,事实上,可空装箱的语义非常接近于发布C# 2.0,这是非常有争议的。

他们为什么决定把它包括进去?

所有的设计都是在许多微妙的、完全不相容的目标中进行选择的过程;我只能简单地概述其中几个需要考虑的因素:

  • 语言特征的正交性通常被认为是一件好事。C#具有可空值类型、非空值类型和可空引用类型.非空引用类型不存在,使得类型系统不正交.
  • 熟悉C、C++和Java的现有用户非常重要。
  • 与COM的简单互操作性很重要。
  • 与所有其他.NET语言的简单互操作性是很重要的。
  • 与数据库的简单互操作性是很重要的。
  • 语义的一致性很重要;如果我们引用等于null的TheKingOfFrance,这是否总是意味着“现在没有法国国王”,还是也意味着“肯定有一个法国国王;我只是不知道现在是谁”?或者这是否意味着“在法国拥有国王的想法是荒谬的,所以甚至不要问这个问题!”Null可能意味着所有这些事情,在C#中更多,所有这些概念都是有用的。
  • 性能成本很重要。
  • 接受静态分析是很重要的。
  • 类型系统的一致性很重要;我们能否始终知道,在任何情况下都不会发现非空引用是无效的?那么,在具有非空引用类型字段的对象的构造函数中呢?在这样一个对象的终结器中,由于应该填充引用的代码抛出了一个异常,所以对象被最后确定了,那么在这个对象的终结器中呢?一种向你隐瞒其担保的类型系统是危险的。
  • 那么语义的一致性又如何呢?空值在使用时会传播,但空引用在使用时会抛出异常。这是不一致的;这种不一致是有好处的吗?
  • 我们能在不破坏其他特性的情况下实现这个特性吗?该功能还排除了哪些其他可能的未来功能?
  • 你和你的军队作战,而不是你想要的军队。请记住,C# 1.0没有泛型,因此将Maybe<T>作为一种替代方案是完全不可能的。当运行时团队添加泛型时,.NET是否应该下滑两年,仅仅是为了消除空引用?
  • 类型系统的一致性如何?你可以对任何价值类型说Nullable<T> --不,等等,那是个谎言。你不能说Nullable<Nullable<T>>。你能做到吗?如果是的话,它想要的语义是什么?为了这个特性,让整个类型系统有一个特例是值得的吗?

诸若此类。这些决定是复杂的。

票数 126
EN

Software Engineering用户

发布于 2014-05-02 19:42:59

Null用于表示缺少值的非常有效的目的。

我要说的是,我是我所知道的最直言不讳的人,尤其是在滥用null的情况下,以及他们可能引起的所有头痛和痛苦。

我个人的立场是,只有当人们能够证明这是必要和适当的时候,他们才能使用零。

验证空值的

示例:

死亡日期通常是可空字段。死亡日期有三种可能的情况。要么该人已死亡且日期已知,该人已死亡且日期不详,要么该人未死亡,因此不存在死亡日期。

死亡日期也是一个DateTime字段,没有“未知”或“空”值。它确实有默认日期,当您根据所使用的语言创建一个新的日期时间时,这个日期会发生变化,但从技术上讲,如果您使用默认日期,那么这个人实际上可能会死掉,并将其标记为您的“空值”。

这些数据需要适当地反映情况。

人死亡日期已知(1984年9月3日)

简单,'3/9/1984‘

人死了死亡日期是未知的

那么什么是最好的呢?Null、'0/0/0000‘或'01/01/1869’(或默认值是什么?)

人未死亡死亡日期不适用

那么什么是最好的呢?Null、'0/0/0000‘或'01/01/1869’(或默认值是什么?)

所以让我们考虑一下每一个价值..。

  • Null,它有一些您需要警惕的暗示和担忧,如果不确定它是非空的,就不小心地操作它--例如,它会抛出一个异常,但它也最好地代表实际情况。如果那个人没有死,死亡的日期就不存在.没什么..。它是无效的..。
  • 0/0/0000,这在某些语言中可能是可以的,甚至可以是没有日期的适当表示。不幸的是,有些语言和验证会将其作为无效的日期时间拒绝,这使得它在许多情况下都是不去的。
  • 1/1/1869年(或者不管您的默认日期时间值是什么),这里的问题是处理起来很棘手。你可以用它作为你的价值缺失,但如果我想过滤掉所有我没有死亡日期的记录会发生什么呢?我可以很容易地过滤掉那些在那一天真正死去的人,这可能会导致数据完整性问题。

事实是,有时您确实不需要表示任何内容,而且有时变量类型可以很好地实现这一点,但通常情况下,变量类型需要能够表示任何内容。

如果我没有苹果,我有0只苹果,但如果我不知道我有多少苹果呢?

当然,null被滥用了,并且具有潜在的危险性,但有时它是必要的。在很多情况下,它只是默认的,因为在我提供一个值之前,缺少一个值,需要一些东西来表示它。(空)

票数 32
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/237697

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档