← Назад к вопросам

В чём разница между virtual/override и new при переопределении методов в C#?

2.2 Middle🔥 181 комментариев
#Entity Framework и ORM#Основы C# и .NET

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI7 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Разница между virtual/override и new в C#

В C# существуют два принципиально разных подхода к переопределению методов: полиморфное virtual/override и статическое new. Разница затрагивает фундаментальные аспекты ООП — полиморфизм и связывание.

Основные концепции

virtual и override работают в связке и обеспечивают полиморфизм времени выполнения (runtime polymorphism). Это означает, что конкретная реализация метода выбирается динамически, в зависимости от фактического типа объекта, а не типа переменной.

new (новое определение метода) создаёт статическое связывание (compile-time binding). В этом случае компилятор выбирает метод на основе типа переменной, а не фактического типа объекта.

Детальное сравнение

Механизм virtual/override

public class Animal
{
    public virtual void MakeSound()
    {
        Console.WriteLine("Some generic animal sound");
    }
}

public class Dog : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("Woof!");
    }
}

// Использование
Animal myAnimal = new Dog();
myAnimal.MakeSound(); // Вывод: "Woof!" - вызывается метод Dog
  • virtual в базовом классе помечает метод как виртуальный — кандидат для переопределения
  • override в производном классе явно указывает, что метод переопределяет родительскую реализацию
  • При вызове через ссылку базового класса выполняется метод производного класса

Механизм new

public class Animal
{
    public void MakeSound()
    {
        Console.WriteLine("Some generic animal sound");
    }
}

public class Dog : Animal
{
    public new void MakeSound()
    {
        Console.WriteLine("Woof!");
    }
}

// Использование
Animal myAnimal = new Dog();
myAnimal.MakeSound(); // Вывод: "Some generic animal sound" - вызывается метод Animal

Dog myDog = new Dog();
myDog.MakeSound(); // Вывод: "Woof!" - вызывается метод Dog
  • new создаёт новый метод, скрывающий родительский, но не переопределяющий его
  • При вызове через ссылку базового класса выполняется метод базового класса
  • При вызове через ссылку производного класса выполняется новый метод

Ключевые различия в таблице

Аспектvirtual/overridenew
Тип полиморфизмаДинамический (runtime)Статический (compile-time)
СвязываниеПозднее (late binding)Раннее (early binding)
Влияние на иерархиюЗаменяет реализацию в иерархииСоздаёт параллельную реализацию
Вызов через базовую ссылкуМетод производного классаМетод базового класса
ПредназначениеИзменение поведения в иерархииДобавление альтернативной реализации

Практические примеры и последствия

public class Base
{
    public virtual void VirtualMethod() => Console.WriteLine("Base Virtual");
    public void NormalMethod() => Console.WriteLine("Base Normal");
}

public class Derived : Base
{
    public override void VirtualMethod() => Console.WriteLine("Derived Override");
    public new void NormalMethod() => Console.WriteLine("Derived New");
}

public class Program
{
    public static void Main()
    {
        Base obj = new Derived();
        
        obj.VirtualMethod(); // "Derived Override" - полиморфизм
        obj.NormalMethod();  // "Base Normal" - скрытие метода
        
        // Для доступа к методу с 'new' нужна ссылка производного типа
        ((Derived)obj).NormalMethod(); // "Derived New"
    }
}

Важные особенности

  1. Предупреждения компилятора: При скрытии метода без явного указания new компилятор выдаёт предупреждение CS0108, рекомендуя явно указать модификатор.

  2. Каскадное переопределение: Метод с override может быть сам переопределён в дальнейшей иерархии, тогда как метод с new начинает новую цепочку.

  3. sealed override: Переопределённый метод можно запечатать с sealed, предотвращая дальнейшее переопределение в производных классах.

  4. Абстрактные методы: abstract методы всегда являются виртуальными и требуют override в производных классах.

Рекомендации по использованию

  • Используйте virtual/override когда:

    • Проектируете иерархию классов с полиморфным поведением
    • Реализуете шаблон "Шаблонный метод"
    • Создаёте плагин-архитектуру или фреймворки
  • Используйте new когда:

    • Нужно добавить метод с тем же именем, но другой семантикой
    • Работаете с библиотеками, где нельзя изменить базовый класс
    • Создаёте параллельную иерархию методов (редкий случай)

Вывод

Основное отличие между virtual/override и new заключается в механизме диспетчеризации вызовов. virtual/override обеспечивает истинный полиморфизм объектов, критически важный для большинства ООП-архитектур, тогда как new создаёт механизм сокрытия, который может приводить к неожиданному поведению и нарушению принципа подстановки Лисков (LSP). В большинстве случаев virtual/override является предпочтительным выбором при проектировании расширяемых систем.

В чём разница между virtual/override и new при переопределении методов в C#? | PrepBro