Переопределение методов в C#

10.01.2019 at 13:20

Наследование — одна из основных концепций объектно-ориентированного программирования. Она говорит о том, что поведение класса-предка может быть переопределено в классе-потомке.

Рассмотрим на примере

public class A 
{
    public virtual void DoWork()
    {
        Console.WriteLine("class A");
    }
}

public class B : A 
{
    public override void DoWork()
    {
        Console.WriteLine("class B");
    }
}

Здесь есть 2 класса: A — предок, B — потомок. В классе A объявлен метод

public virtual void DoWork()

ключевое слово virtual как раз и говорит о том, что этот метод может быть переопределен в потомке.

В классе B этот метод переопределен с помощью ключевого слова override.

работает это так:

var a = new A();
var b = new B();
a.DoWork(); // class A
b.DoWork(); // class B
(b as A).DoWork(); // class B

т.е. не зависимо от того, какого типа переменная, метод будет браться из реального класса.

Перекрытие методов в C#

Изменим класс B следующим образом:

public class B : A 
{
    public void DoWork()
    {
        Console.WriteLine("class B");
    }
}

Отличие в том, что отсутствует ключевое слово override. В этом случае метод предка не переопределен, а перекрыт. В этой ситуации наличие или отсутствие ключевого слова virtual в классе A не имеет значения.

Поведение такого класса будет отличаться:

var a = new A();
var b = new B();
a.DoWork(); // class A
b.DoWork(); // class B
(b as A).DoWork(); // class A

как мы видим, метод берется не из реального класса переменной, а от типа, к которому переменная переопределена. Это неочевидное поведение может быть причиной трудно находимых багов и делать так крайне не рекомендуется. Среда разработки подсветит перекрывающий метод как warning.

Если вам нужно именно такое поведение, нужно помечать перекрывающий метод ключевым словом new

public class B : A 
{
    public new void DoWork()
    {
        Console.WriteLine("class B");
    }
}
Tags: