关于NullReferenceException的困惑

时间:2013-08-15 14:07:26

标签: c# arrays nullreferenceexception

据我所知Console.WriteLine()(或Console.Write())调用对象的ToString()方法来获取对象的字符串represantation对吗?那么对Console.WriteLine()的两次调用是否正确?

Foo foo = new Foo();

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

所以我们假设以下情况。我声明一个实例化一个Foos数组。

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

然后我在数组的任何元素上调用Console.WriteLine()而不实例化Foos本身。所以在这种情况下我们有一个Foos数组,数组中的每个Foo都是null所以调用Console.WriteLine()会导致NullReferenceException被抛出正确吗?但事情是,如果你这样称呼它

Console.WriteLine(foos[0])

除了在控制台窗口中写入Environment.NewLine之外没有任何反应,但如果你这样称呼它

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

它实际上抛出NullReferenceException。这两个电话有什么区别?我的意思是在第一个中我没有明确地调用ToString()但是它不应该被Console.WriteLine()隐式调用吗?如果NullReferenceException在第一种情况下不被抛出怎么办?

3 个答案:

答案 0 :(得分:13)

  

那么这两个对Console.WriteLine()的调用是否正确?

没有。由于Console.WriteLine 不会在空引用上调用ToString,因此它只使用空字符串。它会检测到它自己。

documentation明确说明了这一点:

  

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

没有致电ToString,就没有NullReferenceException

string.Format的行为方式相同。例如:

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

会将text设置为Value: ''

答案 1 :(得分:5)

Console.WriteLine Method (Object)

  

如果值为null,则仅写入行终止符。否则,调用ToString value方法以生成其字符串表示形式,并将结果字符串写入标准输出流。

所以Console.WriteLine(obj)Console.WriteLine(obj.ToString())并不完全相同。

还有一些代码:

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());
}

答案 2 :(得分:0)

Console.WriteLine(foos[0])

在上面的行中,因为它是null,因此根据documentation行终止符将被写入,没有别的。我假设它将首先检查对象是否为null然后写行终止符,否则调用对象上的ToString()方法。而

Console.WriteLine(obj.ToString())

在null上调用ToString方法,这是一个例外。