Разметить виртуальный ToString в базовом классе, что происходит? - PullRequest
3 голосов
/ 09 февраля 2011

Рассмотрим следующий пример (LinqPad). ToString в классе X помечается как виртуальный. Почему вывод здесь не равен «Привет, я Y, Привет, я Х», а вместо этого напечатано имя типа? Конечно, помечать ToString virtual неправильно, потому что он определен в Object как виртуальный, я просто пытаюсь понять, что здесь происходит.

void Main()
{
    Y y = new Y();
    Console.WriteLine(y);
}

// Define other methods and classes here

class X
{
  public virtual String ToString() 
  {
    return "Hi, I'm X";
  }
}

class Y : X
{
  public override String ToString() 
  {
    return "Hi, I'm Y, " + base.ToString();
  }
}

Ответы [ 2 ]

15 голосов
/ 09 февраля 2011

Это создает новый виртуальный метод в X с именем ToString(), который скрывает Object.ToString().Так что если у вас есть:

Y y = new Y();
X x = y;
Object o = y;

Console.WriteLine(y.ToString()); // Shows "Hi, I'm Y, Hi, I'm X";
Console.WriteLine(x.ToString()); // Shows "Hi, I'm Y, Hi, I'm X";
Console.WriteLine(o.ToString()); // Calls object.ToString; shows just "Y"

Вызов только

Console.WriteLine(y);

эквивалентен последней строке, поэтому имя типа печатается.

По сути, вашX.ToString метод должен переопределить метод object.ToString():

public override String ToString() 
{
    return "Hi, I'm X";
}
8 голосов
/ 09 февраля 2011

Используя virtual String ToString() для class X, вы «прячете» object.ToString вместо того, чтобы переопределять его.

Когда вы звоните Console.WriteLine(y);, он вызывает object.ToString().Поскольку вы не переопределяете это, ваш метод никогда не вызывается.

При этом компилятор предупредит вас:

Предупреждение 1 'X.ToString ()' скрывает наследуемоечлен 'object.ToString ()'.Чтобы текущий член переопределил эту реализацию, добавьте ключевое слово override.В противном случае добавьте новое ключевое слово.

...