Почему виртуальные методы должны быть явно переопределены в C#?

Почему виртуальные методы должны быть явно переопределены в C#?

6 ответов

Решение

Объявив метод как virtual, вы заявляете о своем намерении переопределить метод в производном классе.

Объявляя ваш метод реализации как overrideВы заявляете о своем намерении переопределить virtual метод.

Требуя, чтобы override Если ключевое слово используется для переопределения виртуального метода, разработчики языка поощряют ясность, требуя от вас заявить о своих намерениях.

Если вы не добавите override ключевое слово, метод будет скрыт (как если бы он имел new ключевое слово), не переопределяется.

Например:

class Base {
    public virtual void T() { Console.WriteLine("Base"); }
}
class Derived : Base {
    public void T() { Console.WriteLine("Derived"); }
}

Base d = new Derived();
d.T();

Этот код печатает Base, Если вы добавите override к Derived реализация, код напечатает Derived,

Вы не можете сделать это в C++ с помощью виртуального метода. ( Нет способа скрыть виртуальный метод C++ без его переопределения)

Это потому, что все члены команды C# являются опытными программистами C++. И знаете, как возникла эта конкретная ошибка:

class Base {
protected:
    virtual void Mumble(int arg) {}
};

class Derived : public Base {
protected:
    // Override base class method
    void Mumble(long arg) {}
};

Это гораздо чаще, чем вы думаете. Производный класс всегда объявляется в другом файле исходного кода. Как правило, вы не сразу понимаете, что это неправильно, это случается при рефакторинге. Никаких писем от компилятора, код работает довольно нормально, просто не делает то, что вы ожидаете. Вы можете посмотреть на это час или день и не увидеть ошибку.

Это никогда не может произойти в программе на C#. Даже управляемый C++ принял этот синтаксис, преднамеренно нарушая собственный синтаксис C++. Всегда смелый выбор. IntelliSense избавляет от лишних слов.

В C# есть множество доработок синтаксиса, которые напоминают синтаксис такого рода для избежания ошибок.


РЕДАКТИРОВАТЬ: и остальное сообщество C++ согласилось и приняло ключевое слово override в новой спецификации языка C++11.

Потому что это делает код более читабельным:

class Derived : Base
{
    void Foo();
}

В C++ Foo может быть или не быть виртуальным методом, мы не можем сказать, глядя на определение. В C# мы знаем, что метод является виртуальным (или не является), потому что есть ключевое слово virtual или override.

Комментарий Джейсона ниже - лучший ответ.

(отредактировано для ясности)

Не все виртуальные методы должны быть переопределены, хотя все абстрактные методы должны (и должны) быть. Что касается того, почему ключевое слово 'override' является явным, то это потому, что переопределение и скрытие ведут себя по-разному. Скрытый метод не вызывается посредством ссылки на базовый класс, тогда как переопределенный метод -. Вот почему компилятор специально предупреждает о том, как вы должны использовать ключевое слово 'new' в случае, когда вы прячете, а не переопределяете.

Нет необходимости явно переопределять виртуальный метод в производном классе. Маркировка метода как виртуального включает только переопределение.

Другие вопросы по тегам