我们注意到在C#(或Java)中开发的软件中存在很多错误会导致NullReferenceException.
有没有理由为什么"null"甚至被包括在语言中?
毕竟,如果没有"空",我就没有错,对吧?
换句话说,如果没有null,语言中的哪些功能无法工作?
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(); }
无效是引用类型的自然结果.如果你有一个引用,它必须引用一些对象 - 或者为null.如果你要禁止无效,你总是要确保每个变量都用一些非空表达式初始化 - 即使这样,如果在初始化阶段读取了变量,你也会遇到问题.
你会如何建议删除无效的概念?
与面向对象编程中的许多事情一样,这一切都可以追溯到ALGOL.Tony Hoare刚刚称之为"十亿美元的错误".如果有的话,这是轻描淡写的.
这是一个非常有趣的论文,关于如何使可空性不是Java中的默认值.与C#的相似之处显而易见.
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不会解决太多问题.您需要为init上设置的大多数变量设置默认引用.您将获得意外行为,而不是空引用异常,因为该变量指向错误的对象.至少空引用快速失败而不是导致意外行为.
您可以查看null-object模式以获得解决此问题的部分方法
Null是一个非常强大的功能.如果你没有价值,你会怎么做?它是空的!
一种思想是永远不会归零,另一种是永远.例如,有人说你应该返回一个有效但空的对象.
对于我来说,我更喜欢零,这是一个更真实的指示.如果我无法从持久层中检索实体,我想要null.我不想要一些空值.但那就是我.
它对原始人特别方便.例如,如果我有真或假,但它在安全表单上使用,其中权限可以是允许,拒绝或不设置.好吧,我希望不设置为null.所以我可以用bool?
我还有很多事情要做,但我会留在那里.
毕竟,如果没有"空",我就没有错,对吧?
答案是否定的.问题不在于C#允许null,问题是你有错误,它们碰巧用NullReferenceException表现出来.如前所述,空值在语言中的目的是指示"空"引用类型或非值(空/无/未知).
Null不会导致NullPointerExceptions ...
程序员会导致NullPointerExceptions.
如果没有空值,我们将返回使用实际的任意值来确定函数或方法的返回值是无效的.你仍然需要检查返回的-1(或其他),删除空值不会神奇地解决懒惰,但会大量混淆它.
问题可能被解释为"为每个参考类型(如String.Empty)设置默认值还是null?".在这个预期中我宁愿有空,因为;
我不想为我写的每个类编写一个默认构造函数.
我不希望为这样的默认值分配一些不必要的内存.
检查referance是否为null比价值比较便宜.
很可能有更多的错误更难以检测,而不是NullReferanceExceptions.拥有这样的例外是一件好事,这个例外清楚地表明我正在做(假设)错误.