Ответ 1
Вы никогда не превышали версию Base
Print()
. Вы только скрыли его с помощью отдельного виртуального метода (именованного таким же) в Der1
.
Когда вы используете ключевое слово new
в сигнатуре метода - вы сообщаете компилятору, что это метод, который имеет одно имя как метод одного из ваших базовых классов, но не имеет другого отношения. Вы можете сделать этот новый метод виртуальным (как вы это сделали), но это не то же самое, что переопределить метод базового класса.
В Der2
, когда вы переопределяете Print
, вы фактически переопределяете "новую" версию, указанную в Der1
, а не версию Base
. Eric Lippert имеет отличный ответ на несколько другой вопрос, который может помочь вам понять, как обрабатываются виртуальные методы на языке С#.
В вашем примере, когда вы вызываете Print
, вы вызываете его в первом случае посредством ссылки типа Base
- поэтому вызывается скрытая (но не переопределенная) версия Print
. Два других вызова отправляются в реализацию Der1
, так как в этом случае вы действительно завышаете этот метод.
Подробнее об этом можно узнать в документации MSDN для новых и переопределить.
То, что вы, возможно, намеревались сделать с Der1 (как и с Der2), - это использовать ключевое слово override
:
class Base
{
public virtual void Print()
{
Console.WriteLine("Base");
}
}
class Der1 : Base
{
// omitting 'new' and using override here will override Base
public override void Print()
{
Console.WriteLine("Der1");
}
}