关于NullReferenceException的困惑

本文关键字:NullReferenceException 关于 | 更新日期: 2023-09-27 18:27:58

据我所知,Console.WriteLine()(或Console.Write())调用对象的ToString()方法来获得对象的字符串表示,对吗?所以这两个呼叫Console.WriteLine()是一样的,对吧?

Foo foo = new Foo();
Console.WriteLine(foo); // This is same as the one bellow 
Console.WriteLine(foo.ToString());

因此,让我们假设以下情况。我声明一个实例化Foo数组。

Foo[] foos = new Foo[10]; // After this line all 10 Foos are `null`s

然后,我在不实例化Foo本身的情况下,对数组的任何元素调用Console.WriteLine()。所以在这种情况下,我们有一个Foo数组,数组中的每个Foo都是null,所以对Console.WriteLine()的调用应该会导致抛出一个NullReferenceException,对吗?但问题是,如果你把它称为

Console.WriteLine(foos[0])

除了在控制台窗口中写入Environment.NewLine之外,什么都没有发生,但如果你像这样调用它

Console.WriteLine(foos[0].ToString())

它实际上抛出一个CCD_ 8。这两个电话有什么区别?我的意思是,在第一个例子中,我不显式调用ToString(),但Console.WriteLine()不应该隐式调用它吗?在第一种情况下,如何不抛出NullReferenceException

关于NullReferenceException的困惑

所以这两个对Console.WriteLine()的调用是一样的,对吧?

没有。因为Console.WriteLine不会在null引用上调用ToString,所以它只使用空字符串。它自己检测到了这一点。

文件明确指出:

如果值为null,则只写入行终止符。否则,将调用值的ToString方法来生成其字符串表示,并将生成的字符串写入标准输出流。

没有对ToString的调用,就没有NullReferenceException

CCD_ 15的行为方式相同。例如:

object value = null;
string text = string.Format("Value: '{0}'", value);

text设置为Value: ''

Console.WriteLine方法(对象)

如果值为null,则只写入行终止符。否则,将调用值的ToString方法来生成其字符串表示,并将生成的字符串写入标准输出流。

因此CCD_ 20和CCD_ 21并不完全相同。

还有一点代码:

public virtual void WriteLine(object value)
{
    if (value == null)
    {
        this.WriteLine();
        return;
    }
    IFormattable formattable = value as IFormattable;
    if (formattable != null)
    {
        this.WriteLine(formattable.ToString(null, this.FormatProvider));
        return;
    }
    this.WriteLine(value.ToString());
}
Console.WriteLine(foos[0])

在上面的行中,由于它为null,因此根据文档,将编写行终止符,而不编写其他内容。我假设它将首先检查对象是否为null,然后写入行终止符,否则将调用对象上的ToString()方法。而

Console.WriteLine(obj.ToString())

正在对null调用ToString方法,这是一个异常。