为什么 .NET 中存在 null?
为什么 .NET 中的值可以为 null?这是否优于保证所有东西都有值且没有东西为空的保证?
有人知道这些方法的名称是什么吗?
不管怎样,我对此不是很了解,但就简单性而言,并不是所有东西都有一个值会让事情变得更容易,即消除空检查,并能够编写更精简的算法,而不必分支用于检查。
每种风格在性能、简单性、并行性、面向未来等方面都有哪些优缺点?
Why can values be null in .NET? Is this superior to having a guarantee where everything would have a value and nothing call be null?
Anyone knows what each of these methodologies are called?
Either way, I am not very knowledgeable on this, but wouldn't having a value for everything makes things easier, in terms of simplicity, i.e. eliminating null checks, and being able to write more streamlined algorithms that doesn't have to branch out for checks.
What are the pros and cons of each style in terms of performance, simplicity, parallellism, future-proofing, etc.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
我们有 Tony Hoare,他是 Algol 的早期先驱为此表示感谢。他颇为遗憾:
我认为十亿是一个偏低的数字。
更新:C# 版本 8 和 .NETCore 对于此问题有一个不错的解决方案,请查看 不可为 null 的引用类型。
We've got Tony Hoare, an early pioneer that worked on Algol to thank for that. He rather regrets it:
A billion is a low-ball number, I think.
UPDATE: C# version 8 and .NETCore have a decent solution for this problem, check out non-nullable reference types.
尽管没有
null
的世界很有吸引力,但它确实给许多现有模式和构造带来了很多困难。例如,考虑以下构造,如果null
不存在,则需要进行重大更改new object[42]
。在现有的 CLR 世界中,数组将用null
填充,这是非法的。数组语义在这里需要进行相当大的改变,T
是值类型时,它才使default(T)
有用。不允许在引用类型或不受约束的泛型上使用它null
填充引用类型的字段。这在非空世界中是不可能的,因此需要禁止类型为结构中引用类型的字段。上述问题都不是无法解决的,但它们确实会导致真正挑战开发人员如何思考编码的变化。就我个人而言,我希望 C# 和 .Net 的设计能够消除 null,但不幸的是事实并非如此,我想像上面这样的问题与此有一定关系。
As appealing as a world without
null
is, it does present a lot of difficulty for many existing patterns and constructs. For example consider the following constructs which would need major changes ifnull
did not existnew object[42]
. In the existing CLR world the arrays would be filled withnull
which is illegal. Array semantics would need to change quite a bit heredefault(T)
useful only whenT
is a value type. Using it on reference types or unconstrained generics wouldn't be allowednull
. That wouldn't be possible in a non-null world hence fields whos type are reference types in struct's would need to be disallowedNone of the above problems are unsolvable but they do result in changes that really challenge how developers tend to think about coding. Personally I wish C# and .Net was designed with the elimination of null but unfortunately it wasn't and I imagine problems like the above had a bit to do with it.
这让我想起詹姆斯·伯克的《连线》系列中的一集,僧侣们将阿拉伯语抄写成拉丁语,第一次遇到了零数字。罗马算术没有零的表示,但阿拉伯/阿拉姆算术有。 “为什么我们一定要写信表明什么?”天主教修士们争论道。 “如果没什么,我们就什么也不写!”
对于现代社会来说幸运的是,他们输掉了争论并学会了在数学中写出零数字。 ;>
Null 只是表示不存在对象。有些编程语言本身没有“null”,但大多数语言仍然有一些东西来表示合法对象的不存在。如果你扔掉“null”并将其替换为“EmptyObject”或“NullNode”,它仍然是一个 null,只是名称不同。
如果你删除了编程语言表示不引用合法对象的变量或字段的能力,也就是说,你要求每个变量和字段始终包含一个真实有效的对象实例,那么你就做出了一些非常有用和高效的东西。数据结构笨拙且低效,例如构建链表。程序员被迫发明“假”对象实例来充当列表终端,而不是使用 null 来指示链表的末尾,该实例除了指示“这里什么都没有”之外什么都不做。
在这里深入研究存在主义,但是:如果你可以代表某物的存在,那么是否也有基本的需要能够代表它的不存在?
This reminds me of an episode of James Burke's "Connections" series where monks were transcribing arabic to latin and first encountered a zero digit. Roman arithmetic did not have a representation for zero, but arabic/aramaic arithmetic did. "Why do we have to write a letter to indicate nothing?" argued the Catholic monks. "If it is nothing, we should write nothing!"
Fortunately for modern society, they lost the argument and learned to write zero digits in their maths. ;>
Null simply represents an absence of an object. There are programming languages which do not have "null" per se, but most of them do still have something to represent the absence of a legitimate object. If you throw away "null" and replace it with something called "EmptyObject" or "NullNode", it's still a null just with a different name.
If you remove the ability for a programming language to represent a variable or field that does not reference a legitimate object, that is, you require that every variable and field always contain a true and valid object instance, then you make some very useful and efficient data structures awkward and inefficient, such as building a linked list. Instead of using a null to indicate the end of the linked list, the programmer is forced to invent "fake" object instances to serve as list terminals that do nothing but indicate "there's nothing here".
Delving into existentialism here, but: If you can represent the presence of something, then isn't there a fundamental need to be able to represent the absence of it as well?
我推测它们在.NET中存在
null
,因为它(C#)追随了C++/Java的脚步(并且只在更新的版本中开始分支) )和 VB/J++(后来成为 VB.NET/J#)已经有了“无”值的概念——也就是说,.NET 有null
因为曾经而不是因为它可能是什么。在某些语言中,没有
null
的概念 -null
可以完全替换为 Maybe 之类的类型 - - 有 Something(对象)或 Nothing(但这不是null
!没有办法从 Maybe 中得到“Nothing”!)在 Scala 中选项:
这是通过 Haskell 中的语言设计(
null
不可能......根本!)和通过库支持和仔细使用来完成的,例如与 Scala 中一样,如上所示。 (Scala 支持null
——可以说是为了 Java/C# 互操作——但是可以在不使用这个事实的情况下编写 Scala 代码,除非允许“泄漏”null
) 。编辑:请参阅Scala:选项模式 、 Scala:选项 Cheat Cheet 和 SO:在 Haskell 中使用 Maybe Type。大多数时候在 Haskell 中谈论 Maybe 都会提到 Monad 的话题。我不会声称理解它们,但是这里有一个链接以及使用也许吧。
快乐编码。
I speculate that their exists
null
in .NET because it (C#) followed in the C++/Java foot-steps (and has only started to branch-out in more recent versions) and VB/J++ (which became VB.NET/J#) already had the notion of "nothing" values -- that is, .NET hasnull
because of what was and not because of what it could have been.In some languages there is no notion of
null
--null
can be completely replaced with a type like Maybe -- there is Something (the object) or Nothing (but this is notnull
! There is no way to get the "Nothing" out of an Maybe!)In Scala with Option:
This is done by language design in Haskell (
null
not possible ... at all!) and by library support and careful usage such as in Scala, as shown above. (Scala supportsnull
-- arguably for Java/C# interop -- but it is possible to write Scala code without using this fact unlessnull
is allowed to "leak" about).Edit: See Scala: Option Pattern, Scala: Option Cheat Cheet and SO: Use Maybe Type in Haskell. Most of the time talking about Maybe in Haskell brings up the topic of Monads. I won't claim to understand them, but here is a link along with usage of Maybe.
Happy coding.
好的,现在换行到 C#-without-null 的魔术词
控制台上打印了什么?
基本上对我来说,它似乎没有解决任何删除空状态的问题,因为无论如何仍然需要管理可能无效的状态......
哦,购买接口的默认值是什么?哦,还有一个抽象类,当对抽象类中定义的默认值调用一个方法但调用另一个抽象方法时会发生什么? .... .... 为什么哦为什么让模型变得毫无意义,这又是多重继承问题!
一种解决方案是完全更改语法,以实现功能齐全的语法,其中空世界不存在,只有当您希望它们存在时才可能存在......但它不是一种类似 C 的语言和多范式.Net 的内容将会丢失。
可能缺少的是一个 null 传播运算符,当 model 为 null 时,它能够将 null 返回给
model.Thing
,例如model.?.Thing
哦,为了更好地确定答案回答你的问题:
Nothing
,因为它在 VB 中被称为“Nothing”,这会从根本上改变语言,用户从 VB6 切换到 VB.Net 已经花了很多年的时间,这样的范式变化可能会对于语言来说是致命的。Ok now wrap to the magic word of C#-without-null
What is printed on the console?
So basically for me it don't seem to solve anything to remove a null state, as the possibly invalid state still need to be managed anyway...
Oh buy the way what would be the default value of an interface ? Oh and an abstract class what would happen when a method is called on a default value that is defined in the abstract class but that call another method that is abstract ? .... .... Why oh why complicating the model for nothing, it's multiple-inheritance questions all over again !
One solution would be to change the syntax completely to go for a full functional one where the null world doesn't exits, only Maybes when you want them to exists... But it's not a C like language and the multi-paradigm-ness of .Net would be lost.
What might be missing is a null-propagating operator able to return null to
model.Thing
when model is null, likemodel.?.Thing
Oh and for good mesure an answer to your question :
Nothing
as it is called in VB would have radically changed the language, it already took years for users to switch from VB6 to VB.Net such a paradigm change might have been fatal for the language.嗯,值(值类型变量)只能为
null
,因为可空类型是在 Fx2 中引入的。但我想你的意思是:
为什么引用可以为 null ?
这就是参考文献的部分用处。考虑一个 Tree 或 LinkedList,如果没有
null
,它们就不可能(无法结束)。您还可以举出更多示例,但主要是
null
的存在是为了对“可选”属性/关系的概念进行建模。Well, values (value-type vars) can only be
null
since the nullable types were introduced in Fx2.But I suppose you mean:
Why can references be
null
?That is part of the usefulness of references. Consider a Tree or LinkedList, they would not be possible (unable to end) without
null
.You could come up with many more examples, but mainly
null
exists to model the concept of 'optional' properties/relationships.歇斯底里的葡萄干。
这是 C 级语言的后遗症,在 C 级语言中,您依赖于显式的指针操作。现代声明性语言(Mercury、Haskell、OCaml 等)在没有 null 的情况下运行得非常愉快。在那里,每个值都必须显式构造。 “null”的想法是通过“option”类型来处理的,该类型有两个值:“no”(对应于 null)和“yes(x)”(对应于值为 x 的非 null)。您必须解压缩每个选项值才能决定要做什么,因此:没有空指针引用错误。
语言中没有空值可以让你省去很多麻烦,这种想法在高级语言中仍然存在,这确实是一种耻辱。
Hysterical raisins.
It's a hangover from C-level languages where you live on explicit pointer manipulation. Modern declarative languages (Mercury, Haskell, OCaml, etc.) get by quite happily without nulls. There, every value has to be explicitly constructed. The 'null' idea is handled through 'option' types, which have two values, 'no' (corresponding to null) and 'yes(x)' (corresponding to non-null with value x). You have to unpack each option value to decide what to do, hence: no null pointer reference errors.
Not having nulls in a language saves you so much grief, it really is a shame the idea still persists in high-level languages.
我也不熟悉替代方案,但我没有看到 Object.Empty 和 null 之间的区别,除了 null 让您知道当您的代码尝试访问对象时出现了问题,而 Object.Empty 允许处理继续。有时您想要一种行为,有时您想要另一种行为。区分 null 和 Empty 是一个有用的工具。
I'm not familiar with alternatives either, but I don't see a difference between Object.Empty and null, other than null lets you know that something is wrong when your code tries to access the object, wheras Object.Empty allows processing to continue. Sometimes you want one behavior, and sometimes you want the other. Distinguishing null from Empty is a useful tool for that.
表示虚无概念,因为 0 不合适。
现在,您可以通过定义可为 null 的类型为任何值类型指定 Null 值。
我认为我们不能总是为变量指定一个值,因为首先我们必须将其默认为某个值,这就出现了为什么特定值比其他值更具优势的问题。
To denote the nothingness concept, since 0 is not the right fit.
Now you can give any value type a Null value by defining a nullable type.
I think we can't have a value always for the variable because at first we have to default it to some value, and here comes the question why a specific value takes advantage over the others.
许多人可能无法理解没有空值的编码,如果 C# 没有空值,我怀疑它是否会流行到这样的程度。
话虽这么说,一个不错的选择是,如果您想允许可为空引用,则该引用必须显式可为空,就像值类型一样。
例如,
不幸的是,C# 1.0 出来时,还没有 Nullable 的概念;这是 C# 2.0 中添加的。强制引用具有值会破坏旧程序。
Many people probably can't wrap their head around coding without nulls, and if C# didn't have nulls, I doubt it would have caught on to the extent that it has.
That being said, a nice alternative would be, if you want to allow a nullable reference, then the reference would have to be explicitly nullable, like with value types.
For example,
Unfortunately, when C# 1.0 came out, there was no concept of Nullable; that was added in C# 2.0. Forcing references to have values would have broken the older programs.
null
只是引用类型的默认值的名称。如果不允许null
,那么“没有值”的概念不会消失,您只需以不同的方式表示它即可。除了具有特殊的名称之外,此默认值在被误用的情况下还具有特殊的语义 - 即,如果您将其视为有值,而实际上没有值。如果没有
null
:总之:
Tony Hoare 描述的
null
问题通常是由于以下事实造成的:在现代虚拟机出现之前,运行时系统没有像您这样干净地处理误用的null
值有今天。滥用指针/引用确实仍然是一个问题,但是在使用 .NET 或 Java 时跟踪问题往往比以前在 C 中容易。null
is just the name of the default value for a reference type. Ifnull
was not allowed, then the concept of "doesn't have a value" wouldn't go away, you would just represent it in a different way. In addition to having a special name, this default value also has special semantics in the event that it is misused - i.e. if you treat it like there is a value, when in fact there is not.If there were no
null
:In summary:
The problems with
null
described by Tony Hoare are typically due to the fact that prior to modern virtual machines, runtime systems did not have nearly as clean handling of misusednull
values like you have today. Misusing pointers/references does remain a problem, but tracking down the problem when working with .NET or Java tends to be much easier than it used to be in e.g. C.