当前位置:  开发笔记 > 编程语言 > 正文

为什么C#和Java中存在"null"?

如何解决《为什么C#和Java中存在"null"?》经验,为你挑选了9个好方法。

我们注意到在C#(或Java)中开发的软件中存在很多错误会导致NullReferenceException.

有没有理由为什么"null"甚至被包括在语言中?

毕竟,如果没有"空",我就没有错,对吧?

换句话说,如果没有null,语言中的哪些功能无法工作?



1> Julien Hoara..:

Anders Hejlsberg,"C#father",刚刚在他的Computerworld采访中谈到了这一点:

例如,在类型系统中,我们没有值和引用类型之间的分离以及类型的可空性.这可能听起来有点不稳定或有点技术性,但在C#中,引用类型可以为null,例如字符串,但值类型不能为null.拥有非可空引用类型肯定会很好,所以你可以声明'这个字符串永远不能为空,我希望你编译器检查我永远不会在这里命中空指针'.

今天人们遇到的50%的bug,在我们的平台上用C#编码,对于Java来说也是如此,可能是空引用异常.如果我们有一个更强大的类型系统,可以让你说"这个参数可能永远不会为空,而你编译器请在每次调用时检查一下,通过对代码进行静态分析".然后我们就可以剔除各种错误.

Cyrus Najmabadi是C#团队(现在在谷歌工作)的前软件设计工程师,他在博客上讨论了这个问题:(第1,第2,第3,第4).似乎采用非可空类型的最大障碍是符号会扰乱程序员的习惯和代码库.像70%的C#程序引用这样的东西很可能最终成为不可空的.

如果你真的想在C#中使用不可为空的引用类型,你应该尝试使用Spec# ,这是一个允许使用"!"的C#扩展名.作为一个不可空的标志.

static string AcceptNotNullObject(object! s)
{
    return s.ToString();
}


实际上所有类型都应该是隐式非可空的,甚至是引用类型.可以为Nullable的类型(值类型以及引用类型)明确标记为"?".
小修正:Cyrus Najmabadi不再是C#团队.直到我今天收到他发来的内部电子邮件,我才知道这件事,这里是谷歌:)

2> Jon Skeet..:

无效是引用类型的自然结果.如果你有一个引用,它必须引用一些对象 - 或者为null.如果你要禁止无效,你总是要确保每个变量都用一些非空表达式初始化 - 即使这样,如果在初始化阶段读取了变量,你也会遇到问题.

你会如何建议删除无效的概念?


在纯函数式编程中,只能通过函数参数和表达式计算(包括函数调用)来指定值,这些值在使用之前都需要指定,并且只有在定义的范围内才存在,除非在闭包中捕获.
它不是根本的.您可以要求任何ref类型变量初始化,就像(非可空)值类型一样.但这会很麻烦.
@Jon,名称"nullity"下有2个概念:未初始化和可选.这就是Algol遗留下来的错误.
简而言之:可能存在各种方法,但是当你查看边缘情况时,它们会变得越来越迷宫.

3> Craig Stuntz..:

与面向对象编程中的许多事情一样,这一切都可以追溯到ALGOL.Tony Hoare刚刚称之为"十亿美元的错误".如果有的话,这是轻描淡写的.

这是一个非常有趣的论文,关于如何使可空性不是Java中的默认值.与C#的相似之处显而易见.



4> Mark Cidade..:

C#中的Null主要是来自C++的结转,其指针指向内存中的任何内容(或者更确切地说是地址0x00).在这次访谈中,Anders Hejlsberg表示他希望在C#中添加不可为空的引用类型.

还空在一个类型系统中的合法地位,但是,作为一个类似于在底部类型(其中object顶级型).在lisp中,底部类型是NIL和Scala一样Nothing.

它会一直可以设计C#没有任何空,但随后你就必须拿出与人们通常的用途可接受的解决方案null,如unitialized-value,not-found,default-value,undefined-value,和None.如果C++和Java程序员确实在这方面取得了成功,那么他们的采用可能会少一些.至少在他们看到C#程序从未有任何空指针异常之前.


更不用说你真正要做的就是重命名为null.
我很惊讶有些人(见上面的Telos)仍然混淆None和Null.我主要不同意第2段:Null在现代类型系统中没有合法的位置.Null是与每个引用类型兼容的单个值,None 不是因为它是参数的.这是一个巨大的差异.downvote可能有点苛刻,但海报似乎暗示有些人使用"未初始化的价值"这是错误的.

5> Mendelt..:

删除null不会解决太多问题.您需要为init上设置的大多数变量设置默认引用.您将获得意外行为,而不是空引用异常,因为该变量指向错误的对象.至少空引用快速失败而不是导致意外行为.

您可以查看null-object模式以获得解决此问题的部分方法


我称之为废话.引入不可为空的引用类型可以让您选择所需的引用类型.OCaml和Haskell具有不可为空的引用,但适用于所有问题域,并且根本不会受到NullReferenceException的影响......

6> mattlant..:

Null是一个非常强大的功能.如果你没有价值,你会怎么做?它是空的!

一种思想是永远不会归零,另一种是永远.例如,有人说你应该返回一个有效但空的对象.

对于我来说,我更喜欢零,这是一个更真实的指示.如果我无法从持久层中检索实体,我想要null.我不想要一些空值.但那就是我.

它对原始人特别方便.例如,如果我有真或假,但它在安全表单上使用,其中权限可以是允许,拒绝或不设置.好吧,我希望不设置为null.所以我可以用bool?

我还有很多事情要做,但我会留在那里.


Allow/Deny/NotSet情况下你想要的是一个枚举,而不是包含null的东西.
False,True,FileNotFound.:-)

7> pro3carp3..:

毕竟,如果没有"空",我就没有错,对吧?

答案是否定的.问题不在于C#允许null,问题是你有错误,它们碰巧用NullReferenceException表现出来.如前所述,空值在语言中的目的是指示"空"引用类型或非值(空/无/未知).


从语言中删除null将减少某些类别的错误的可能性,就像删除指针类型降低某些类别的错误的概率一样.如果你真的需要null,你可以使用不安全的块.值类型存在很好而不可为空.
pro3carp3试图做的一点是,大多数空缺陷与使用未初始化的变量有关,就像它们准备好使用一样.非可空类型实际上只解决了"我不在乎我只想运行这种方法的价值"的情况,而通常你会关心.

8> Newtopian..:

Null不会导致NullPointerExceptions ...

程序员会导致NullPointerExceptions.

如果没有空值,我们将返回使用实际的任意值来确定函数或方法的返回值是无效的.你仍然需要检查返回的-1(或其他),删除空值不会神奇地解决懒惰,但会大量混淆它.



9> tafa..:

问题可能被解释为"为每个参考类型(如String.Empty)设置默认值还是null?".在这个预期中我宁愿有空,因为;

我不想为我写的每个类编写一个默认构造函数.

我不希望为这样的默认值分配一些不必要的内存.

检查referance是否为null比价值比较便宜.

很可能有更多的错误更难以检测,而不是NullReferanceExceptions.拥有这样的例外是一件好事,这个例外清楚地表明我正在做(假设)错误.

推荐阅读
mobiledu2402851323
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有