В чем разница между переопределением и новыми ключевыми словами В C#?


в чем разница между override и new ключевые слова в C# при определении методов в иерархии классов?

5 58

5 ответов:

на следующей странице очень хорошо резюмируется ваш вопрос.

зная, когда использовать переопределение и новые ключевые слова

резюме

переопределить: когда метод базового класса переопределяется в производном классе, используется версия в производном классе, даже если вызывающий код не "знал", что объект является экземпляром производного класса.

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

Если вы не укажете ни new, ни overrides, результат будет таким же, как если бы вы указали new, но вы также получите предупреждение компилятора (поскольку вы можете не знать, что вы скрываете метод в методе базового класса, или действительно Вы, возможно, хотели его переопределить и просто забыли включить ключевое слово).

переопределить: используется виртуальные/абстрактные/переопределение метода в базовом классе

новая: когда базовый класс не объявил метод как virtual / abstract / override

new будет затенять метод с помощью совершенно нового метода (который может иметь или не иметь ту же подпись) вместо его переопределения (в этом случае новый метод должен иметь ту же подпись), что означает, что полиморфизм не будет работать. Например, у вас есть следующие классы:

class A {
    public virtual int Hello() {
        return 1;
    }
}

class B : A {
    new public int Hello(object newParam) {
        return 2;
    }
}

class C : A {
    public override int Hello() {
        return 3;
    }
}

если вы сделаете это:

A objectA;
B objectB = new B();
C objectC = new C();

Console.WriteLine(objectB.Hello(null)); // 2
Console.WriteLine(objectC.Hello()); // 3

objectA = objectB;

Console.WriteLine(objectA.Hello()); // 1

objectA = objectC;

Console.WriteLine(objectA.Hello()); // 3

так как вы можете определить новые сигнатуры метода с new, компилятор не может знать, что экземпляр A на самом деле экземпляр B и новый метод B определение должно быть доступно. new может использоваться, если метод, свойство, поле или событие родительского объекта не объявлены с помощью virtual, и из-за отсутствия virtual компилятор не будет" искать " унаследованный метод. С virtual и override, однако, он работает.

я настоятельно рекомендую вам избегать new; в лучшем случае, это сбивает с толку, потому что вы определяете метод с именем, которое может быть признано как что-то в противном случае, и в худшем случае, он может скрывать ошибки, вводить кажущиеся невозможными ошибки и затруднять расширение функциональности.

похоже, старый вопрос, Позвольте мне попробовать другой ответ:

  1. new : как следует из названия, это новый элемент в семействе иерархии наследования, и он будет использоваться в качестве базового элемента для дальнейшего вниз по цепочке (если он помечен как виртуальный).

  2. override: это означает, что я не принимаю реализацию члена моего родительского класса, и я буду делать по-другому.

рассмотрим следующую иерархию классов:

using System;

namespace ConsoleApp
{     
     public static class Program
     {   
          public static void Main(string[] args)
          {    
               Overrider overrider = new Overrider();
               Base base1 = overrider;
               overrider.Foo();
               base1.Foo();

               Hider hider = new Hider();
               Base base2 = hider;
               hider.Foo();
               base2.Foo();
          }   
     }   

     public class Base
     {
         public virtual void Foo()
         {
             Console.WriteLine("Base      => Foo");
         }
     }

     public class Overrider : Base
     {
         public override void Foo()
         {
             Console.WriteLine("Overrider => Foo");
         }
     }

     public class Hider : Base
     {
         public new void Foo()
         {
             Console.WriteLine("Hider     => Foo");
         }
     }
}    

вывод вышеуказанных кодов должен быть:

Overrider => Foo
Overrider => Foo

Hider     => Foo
Base      => Foo
  • подкласс overrides виртуальный метод, применяя override modifier:
  • если вы хотите hide член сознательно, в этом случае вы можете применить new modifier к члену в подклассе. The new modifier does nothing more than suppress the compiler warning that would otherwise result

override позволяет переопределить виртуальный метод в базовом классе, чтобы можно было использовать другую реализацию. new скроет невиртуальный метод в базовом классе.