参考类型的基本原理超过零

  • 本文关键字:类型 参考 c#
  • 更新时间 :
  • 英文 :


我是C++背景语言的新手,很难理解允许引用类型为null的原因。

考虑以下片段

class Person {
private string _name;
public Person(string name) {_name = name;}
void print() {
Console.WriteLine(_name);
}
}

现在没有什么可以阻止呼叫者进行以下

Person p = new Person(null);
p.print();

这将崩溃,如果null被传递给构造函数,我可以通过抛出异常来保护这一点(不是真的),但这只意味着如果没有捕获到第一行(我不能在C#中强制执行AFAIK),我会在第二行崩溃。

调用者必须阅读文档(这意味着我不能忘记构造函数可能抛出的文档)才能知道所有这些。

  • 语言允许空引用类型的原因是什么
  • 什么时候这才是有利的,而不仅仅是一颗滴答作响的定时炸弹?我能想到的一种情况是惰性初始化,想要有条件地分配对象
  • 如何在我编写的代码中处理此问题

语言允许空引用的原因(似乎)是什么类型?

我可能会在一张纸上放一个盒子,写下"谁是没有眼睛的人?"的答案。我没有那个问题的答案,所以我把方框留空。空白的盒子对此没有反应,着火了,并强迫我的手。。。正如预期的那样,它只是保持空白。

什么时候这是有利的,而不仅仅是一颗滴答作响的定时炸弹?那个我能想到的情况是惰性初始化,想要分配对象。

我有一个功能,可以处理"没有眼睛的人",然而,那个人有时并不存在。我可能会发现这些情况并做出不同的反应。

如何在编写的代码中处理此问题?

空检查。欢迎来到2018,你们这些c++裸金属家伙有很多东西要学习。这是你已经知道的东西,但这些知识存在于其他地方,似乎并不相关。。直到现在。

语言允许空引用类型的原因是什么?

有时你想要一些而不是有值的东西。例如,考虑具有父子关系的节点类。如果Parent永远不能为空,那将是非常不愉快的。即使在C++中,指针也可以指向"nothing",就像在0中一样。

如何在编写的代码中处理此问题?

这从第一天起就一直是个问题。C#团队一直希望我们作为开发人员通过足够的空检查来"解决"这个问题。这就是我们一直在做的事情。

现在,有了C#8(仍在开发中),就有了可以为null的引用类型。启用后,如果一个可能不是null的变量被赋值为null,或者可能为null,则会出现编译器错误。

如果我们颠倒问题。。。

既然你来自C++,我们可以问"C++如何处理不能为null的引用"。简单的答案是"好吧,它有空指针,所以它不需要空引用"。有两种不同类型的变量来表示对对象的引用(具有非常不同的规则和语法)使C++变得更加简单。

是的,Tony Hoare声称空引用是他的"十亿美元的错误"。然而,如果你没有一种方法来表示一个未分配的引用,那么很难用一个简单的语法来获得一种有效的C族语言。

考虑一下这个简单的C#代码:

string myString;
if (condition) {
myString = func1();
} else {
mystring = func2();
}
UseTheString(myString);

字符串变量必须在外部作用域中声明。如果每个引用变量都需要在声明时初始化(比如C++引用),那么您需要用几行后丢弃的东西来初始化它。是的,你可能会说,这就是string.Empty的作用。比System更复杂的类型呢。构造成本更高的字符串类型?它们是否都需要具有unassigned值;已经非常接近null了。嘿,JavaScript同时具有(null和unassigned)!

C++引用非常方便,但它们也非常具有约束性。它们不仅在声明时必须被赋值,而且是不可变的(变量,而不是它们引用的对象)。一旦你声明并初始化了一个C++引用,你就不能改变它引用的内容。如果C#引用遵循这个规则,下面的代码会很有趣(忽略循环中的字符串串联几乎总是一个坏主意):

string myString = string.Empty;
for (var i = 0; i < someValue; ++i) {
myString = myString + SomeFunc(i);
}

然后,还有一些自然为null的东西需要考虑,比如关系数据库中可为null的内容。可以为null的值类型(Nullable<T>)出现在该框架v1之后的第一个主要版本中也就不足为奇了。我们中的许多人还记得(我们中的一些人仍然在处理)DbNull类型(和值)的痛苦。

是的,应对零是一种痛苦。它存在于大多数(但不是所有)语言中。C#语言(引用类型和值类型的组合共享一个变量语法)比C++更容易阅读/理解/拾取。我发现我在C#中写的错误比我作为C++程序员时少了很多(尽管,在语言最近发生变化之前,我是一名90年代的C++程序员)。

C#8.0的人认为他们有一个解决方案(这不是一个完整的解决方案,但它应该会使空引用异常更加罕见)。我很好奇你对C#如何避免霍尔博士数十亿美元的错误有什么看法。

这样null就不会用作值。

class Program
{
static void Main(string[] args)
{
Person person = new Person(null);
person.PrintName();
}
}
class Person
{
private string Name { get; set; }
public Person(string name)
{
this.Name = name ?? "My name can't be null";
}
public void PrintName()
{
Console.WriteLine(this.Name);
}
}

最新更新