Вы никогда не отменяли Base
версию Print()
. Вы только спрятали его с помощью отдельного виртуального метода (названного так же) в Der1
.
Когда вы используете ключевое слово new
в сигнатуре метода - вы говорите компилятору, что этот метод имеет то же имя, что и метод одного из ваших базовых классов, - но не имеет никакого другого отношения. Вы можете сделать этот новый метод виртуальным (как вы это сделали), но это не то же самое, что переопределение метода базового класса.
В Der2
когда вы переопределяете Print
, вы фактически переопределяете 'новую' версию, которую вы объявили в Der1
, а не версию Base
. У Эрика Липперта отличный ответ на немного другой вопрос, который может помочь вам понять, как обрабатываются виртуальные методы в языке C #.
В вашем примере, когда вы вызываете 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");
}
}