对于引用类型,超出null的理由

时间:2018-08-31 14:32:01

标签: 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 ),而不是第二行。

调用者必须阅读文档(这意味着我不能忘记记录构造函数可能抛出的文档)以了解所有这些信息。

  • 语言允许使用空引用类型的原因是(有可能)是什么?
  • 什么时候有利,而不仅仅是定时炸弹?我能想到的一种情况是延迟初始化,想有条件地分配一个对象。
  • 如何在编写的代码中处理此问题?

4 个答案:

答案 0 :(得分:2)

  

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

我可能在纸上有一个盒子,上面写着“谁是没有眼睛的男人?”的答案。我没有这个问题的答案,所以我将方框留空。空白框对此无反应,着火并用力……只是按预期保持空白。

  

什么时候有利,而不仅仅是定时炸弹?唯一的那个   我能想到的是惰性初始化,想分配一个   有条件的对象。

我具有可以处理“没有眼睛的男人”的功能,但是,有时候男人不存在。我可能会发现这些情况并做出不同的反应。

  

我该如何在编写的代码中处理这个问题?

空检查。欢迎来到2018年,您c ++裸机专家有 alot 可以学习。这是您已经知道的东西,但是这些知识存在于其他地方,直到现在似乎都没有意义。

答案 1 :(得分:2)

  

语言允许使用空引用类型的原因是(有可能)是什么?

有时候您想要的东西具有价值。例如,考虑具有父子关系的节点类。如果Parent永远不能为null,那将是非常不愉快的。甚至在C ++中,指针也可以指向“无”,例如0

  

我该如何在编写的代码中处理这个问题?

从第一天开始就一直是一个问题。C#团队一直希望我们作为开发人员通过进行足够的null检查来“解决”此问题。这就是我们一直在做的。

现在,在C#8(仍在开发中)中,有nullable reference types。启用后,如果将可能不为null的变量分配为null或可能为null,则会出现编译器错误。

答案 2 :(得分:1)

如果我们反问...

由于您来自C ++,因此我们可以问“ C ++如何摆脱不能为null的引用”。简单的答案是“嗯,它具有空指针,因此它不需要空引用”。具有两种不同类型的变量来表示对对象的引用(具有不同的规则和语法),这使得C ++ 非常简单

是的,Tony Hoare声称空引用是他的“十亿美元的错误”。但是,如果您没有一种方法来表示未分配的引用,则很难使用简单的语法来获得可用的C系列语言。

考虑以下简单的C#代码:

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

必须在外部范围中声明字符串变量。如果每个引用变量都需要在声明时进行初始化(例如C ++引用),那么您需要使用一些会被扔掉几行的东西来对其进行初始化。是的,您可能会说,这就是string.Empty的目的。比System.String更复杂的类型呢-构造起来更昂贵的类型呢?他们是否都需要一个unassigned值;越来越接近null。嘿,JavaScript既有(null也有未分配的)!

C ++参考非常方便,但它们也非常有约束力。在声明它们时,不仅必须为其分配某些内容,而且它们也是不可变的(变量-而不是它们所引用的对象)。声明并初始化C ++引用后,您将无法更改其引用的内容。如果C#引用遵循此规则,则下面的代码将很有趣(忽略这样的事实:循环中的字符串连接几乎总是一个坏主意):

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

然后,有些事情自然会被考虑为空,例如关系数据库中的可为空的东西。可以为空的值类型(Nullable<T>)出现在框架的第一个主要后继版本中也就不足为奇了。我们很多人都记得(而且我们中有些人仍在应付)DbNull类型(和值)的痛苦。

是的,应付空值是一种痛苦。大多数(但不是全部)语言中都有它。 C#语言(具有引用类型和值类型的组合,共享一种变量语法)比C ++易于阅读/理解/提取。我发现与使用C ++程序员相比,用C#编写的错误更少(尽管,在最近对语言进行所有更改之前,我是90年代的C ++程序员)。

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

答案 3 :(得分:0)

这样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);
    }
}