为什么.NET中的值为null?这是否优于保证所有内容都有值且没有任何调用为空?
任何人都知道这些方法的名称是什么?
无论哪种方式,我对此都知之甚少,但在简单性方面,即在消除空检查方面,并且能够编写更多不具备的简化算法分支出来进行检查。
每种风格在性能,简洁性,平行性,面向未来等方面的优缺点是什么。
答案 0 :(得分:37)
我们有Tony Hoare,这是早期的先驱者,感谢Algol对此表示感谢。他很后悔:
我称之为十亿美元的错误。 这是null的发明 在1965年参考。当时,我是 设计第一个综合类型 用于对象中引用的系统 面向语言(ALGOL W)。我的目标 是为了确保所有的使用 引用应绝对安全, 检查自动执行 由编译器。但我无法抗拒 投入无效的诱惑 参考,仅仅因为它是如此 易于实施。这导致了 无数错误,漏洞, 和系统崩溃,有 可能造成了十亿美元的损失 最后四十年的痛苦和伤害 年。
我认为十亿是一个低球数。
答案 1 :(得分:24)
尽管没有null
的世界很吸引人,但它确实给许多现有的模式和结构带来了很多困难。例如,考虑以下构造,如果null
不存在则需要进行重大更改
new object[42]
。在现有的CLR世界中,数组将填充null
,这是非法的。数组语义需要在这里改变一下default(T)
是值类型时才会使T
有用。不允许在引用类型或无约束泛型上使用它null
填充引用类型的字段。在非空世界中这是不可能的,因此需要禁止类型为struct的引用类型的字段上述问题都不是无法解决的,但它们确实会带来真正挑战开发人员如何考虑编码的变化。我个人希望C#和.Net的设计是为了消除null,但不幸的是它不是,我想像上面的问题有点与它有关。
答案 2 :(得分:9)
这让我想起詹姆斯伯克的“连线”系列剧集,其中僧侣正在将阿拉伯语抄写成拉丁语,并且首次遇到零数字。罗马算术没有零的表示,但阿拉伯语/ aramaic算法确实如此。 “为什么我们要写一封信来表示什么?”争辩天主教僧侣。 “如果没什么,我们应该什么都不写!”
幸运的是,对于现代社会来说,他们失去了争论并学会了在数学中写出零位数。 ;>
Null只表示没有对象。有些编程语言本身没有“null”,但是大多数编程语言仍然有代表缺少合法对象的东西。如果你丢弃“null”并将其替换为名为“EmptyObject”或“NullNode”的东西,那么它仍然是一个带有不同名称的null。
如果你删除编程语言表示不引用合法对象的变量或字段的能力,也就是说,你要求每个变量和字段总是包含一个真实有效的对象实例,那你就做了一些非常好的事情。有用且高效的数据结构笨拙且效率低下,例如构建链表。程序员不必使用null来指示链表的结尾,而是强制发明“假”对象实例作为列表终端,除了表示“此处没有”之外什么都不做。
在这里深入研究存在主义,但是:如果你可以表现出某种东西的存在,那么是否还有一种基本的需要能够代表它的存在呢?
答案 3 :(得分:6)
我推测他们在.NET中存在null
,因为它(C#)遵循C ++ / Java脚步(并且在最近的版本中才开始分支出来) )和VB / J ++(成为VB.NET / J#)已经有了“没有”值的概念 - 也就是说,.NET由于是而没有null
可能的内容。
在某些语言中没有null
的概念 - null
可以完全替换为类似Maybe的类型 - 有某事物(物体)或者没什么(但这不是null
!没有办法从“没有”中获得“没什么”!)
在Scala中使用选项:
val opt = Some("foo") // or perhaps, None
opt match {
case Some(x) => x.toString() // x not null here, but only by code-contract, e.g. Some(null) would allow it.
case _ => "nothing :(" // opt contained "Nothing"
}
这是通过Haskell中的语言设计完成的(null
根本不可能!)和通过库支持和谨慎使用等来完成Scala,如上所示。 (Scala支持null
- 可以说是Java / C#interop - 但是可以编写Scala代码而不使用这个事实,除非允许null
“泄漏”。
修改:查看Scala: Option Pattern,Scala: Option Cheat Cheet和SO: Use Maybe Type in Haskell。大多数时候在Haskell谈论Maybe会带来Monads的主题。我不会声称理解它们,但是here is a link along with usage of Maybe。
快乐的编码。
答案 4 :(得分:5)
好的,现在用C#-without-null
的神奇单词换行class View
{
Model model;
public View(Model model)
{
Console.WriteLine("my model : {0}, thing : {1}", this.model, this.model.thing);
this.model = model;
}
}
控制台上印有什么?
所以基本上对我来说,似乎没有解决任何问题来删除null状态,因为仍然需要管理可能无效的状态......
哦,购买接口默认值的方式?哦,一个抽象类,当在抽象类中定义的默认值上调用方法但是调用另一个抽象方法时会发生什么? .... ....为什么哦为什么一劳永逸地使模型复杂化,这又是多重继承问题!
一种解决方案是完全改变语法以获得一个完整的功能,其中null世界不会退出,只有当你希望它们存在时才是Maybes ...但它不是一个C语言和多个.Net的范式将会丢失。
可能缺少的是一个null传播的运算符,当model为null时,它可以返回null model.Thing
,如model.?.Thing
哦,好好回答你的问题:
Nothing
的框架,因为在VB中调用它会彻底改变语言,用户从VB6切换到VB.Net需要花费数年的时间才能改变范式对这种语言来说是致命的。答案 5 :(得分:3)
嗯,值(值类型变量)只能是null
,因为可空类型是在Fx2中引入的。
但我想你的意思是:
null
?这是参考文献有用性的一部分。考虑一个Tree或LinkedList,如果没有null
,它们将无法(无法结束)。
您可以提出更多示例,但主要是null
来模拟“可选”属性/关系的概念。
答案 6 :(得分:3)
歇斯底里的葡萄干。
这是来自C级语言的宿醉,您可以使用显式指针操作。现代的声明性语言(Mercury,Haskell,OCaml等)非常幸福地得到了没有空值。在那里,每个值都必须明确构建。 'null'思想是通过'option'类型处理的,它们有两个值,'no'(对应于null)和'yes(x)'(对应于值为x的非null)。您必须解压每个选项值以决定要做什么,因此:没有空指针引用错误。
语言中没有空值会让你感到非常悲痛,这种想法仍然存在于高级语言中真的很遗憾。
答案 7 :(得分:2)
我也不熟悉替代方案,但是我没有看到Object.Empty和null之间的区别,除了null之外,当你的代码试图访问对象时,会让你知道出了什么问题,对象是Object.Empty允许处理继续。有时你想要一个行为,有时你想要另一个行为。区分null和Empty是一个很有用的工具。
答案 8 :(得分:1)
表示虚无概念,因为0不合适。
现在,您可以通过定义可空类型为任何值类型提供Null值。
我认为我们不能总是为变量赋值,因为首先我们必须将它默认为某个值,这就是为什么特定值优于其他值的问题。
答案 9 :(得分:1)
许多人可能无法在没有空值的情况下绕过编码,如果C#没有空值,我怀疑它是否已经达到了它的范围。
话虽如此,一个不错的选择是,如果你想允许一个可以为空的引用,那么引用必须是明确可为空的,就像值类型一样。
例如,
Person? person = SearchForPersonByFirstName("Steve");
if (person.HasValue)
{
Console.WriteLine("Hi, " + person.Value.FullName);
}
不幸的是,当C#1.0问世时,没有Nullable的概念;这是在C#2.0中添加的。强制引用具有值会破坏旧程序。
答案 10 :(得分:1)
null
只是引用类型的默认值的名称。如果不允许null
,那么“没有价值”的概念就不会消失,你只会以不同的方式表示它。除了具有特殊名称之外,该默认值在被滥用的情况下也具有特殊语义 - 即,如果您将其视为有值,则实际上没有。
如果没有null
:
总结:
Tony Hoare描述的null
问题通常是由于在现代虚拟机之前,运行时系统几乎没有像今天这样干净处理误用的null
值。滥用指针/引用仍然是一个问题,但是在使用.NET或Java时追踪问题往往比以前更容易 。下进行。