C# - Keyword usage virtual + override vs. new

Jakie są różnice między zadeklarowaniem metody w typie bazowym "virtual" a nadpisaniem jej w typie potomnym przy użyciu słowa kluczowego "override" w przeciwieństwie do zwykłego użycia słowa kluczowego "new" podczas deklarowania metody dopasowania w typie potomnym?

Author: i3ensays, 2008-10-02

9 answers

Słowo kluczowe "new" nie nadpisuje, oznacza nową metodę, która nie ma nic wspólnego z metodą klasy bazowej.

public class Foo
{
     public bool DoSomething() { return false; }
}

public class Bar : Foo
{
     public new bool DoSomething() { return true; }
}

public class Test
{
    public static void Main ()
    {
        Foo test = new Bar ();
        Console.WriteLine (test.DoSomething ());
    }
}

To wyświetla false, jeśli użyłeś override to wyświetli true.

(kod bazowy zaczerpnięty od Josepha Daigle ' a)

Więc, jeśli robisz prawdziwy polimorfizm, zawsze powinieneś nadpisać . Jedynym miejscem, gdzie trzeba użyć "new" jest sytuacja, gdy metoda nie jest w żaden sposób powiązana z wersją klasy bazowej.

 172
Author: albertein,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-09 16:56:36

Zawsze takie rzeczy łatwiej zrozumieć ze zdjęciami:

Ponownie, biorąc kod Josepha daigle ' a,

public class Foo
{
     public /*virtual*/ bool DoSomething() { return false; }
}

public class Bar : Foo
{
     public /*override or new*/ bool DoSomething() { return true; }
}

Jeśli wywołasz kod w ten sposób:

Foo a = new Bar();
a.DoSomething();

Uwaga: ważne jest to, że nasz obiekt jest w rzeczywistości Bar, ale przechowujemy go w zmiennej typu Foo (jest to podobne do odlewania go)

Wtedy wynik będzie następujący, w zależności od tego, czy użyłeś virtual/override lub new podczas deklarowania swojego klasy.

Virtual / Override Explanation

 217
Author: Orion Edwards,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-08 14:08:24

Oto kod, aby zrozumieć różnicę w zachowaniu metod wirtualnych i nie wirtualnych:

class A
{
    public void foo()
    {
        Console.WriteLine("A::foo()");
    }
    public virtual void bar()
    {
        Console.WriteLine("A::bar()");
    }
}

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

class Program
{
    static int Main(string[] args)
    {
        B b = new B();
        A a = b;
        a.foo(); // Prints A::foo
        b.foo(); // Prints B::foo
        a.bar(); // Prints B::bar
        b.bar(); // Prints B::bar
        return 0;
    }
}
 40
Author: Franci Penov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-01 22:15:01

Słowo kluczowe new w rzeczywistości tworzy zupełnie nowy element, który istnieje tylko dla tego konkretnego typu.

Na przykład

public class Foo
{
     public bool DoSomething() { return false; }
}

public class Bar : Foo
{
     public new bool DoSomething() { return true; }
}

Metoda istnieje na obu typach. Kiedy używasz reflection i otrzymujesz elementy typu Bar, w rzeczywistości znajdziesz 2 metody o nazwie DoSomething(), które wyglądają dokładnie tak samo. Używając new skutecznie ukrywasz implementację w klasie bazowej, tak, że gdy klasy wywodzą się z Bar (w moim przykładzie), wywołanie metody do base.DoSomething() przechodzi do Bar, a nie Foo.

 18
Author: Joseph Daigle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-01 22:15:24

Virtual / override mówi kompilatorowi, że obie metody są ze sobą powiązane i że w pewnych okolicznościach, gdy wydaje się, że wywołujesz pierwszą (wirtualną) metodę, właściwe jest wywołanie drugiej (nadpisanej) metody. To jest podstawa polimorfizmu.

(new SubClass() as BaseClass).VirtualFoo()

Wywoła nadpisaną metodę VirtualFoo() podklasy.

New mówi kompilatorowi, że dodajesz metodę do klasy pochodnej o tej samej nazwie, co metoda w klasy bazowej, ale nie mają ze sobą żadnego związku.

(new SubClass() as BaseClass).NewBar()

Wywoła metodę NewBar() BaseClass, natomiast:

(new SubClass()).NewBar()

Wywoła metodę NewBar() podklasy.

 9
Author: Wedge,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-01 22:24:02

Poza szczegółami technicznymi, myślę, że użycie virtual / override przekazuje wiele semantycznych informacji na temat projektu. Deklarując metodę wirtualną, wskazujesz, że spodziewasz się, że klasy implementujące mogą chcieć dostarczyć własne, niestandardowe implementacje. Pominięcie tego w klasie bazowej, podobnie, deklaruje oczekiwanie, że domyślna metoda powinna wystarczyć dla wszystkich klas implementujących. Podobnie można użyć abstrakcyjnych deklaracji, aby wymusić implementację klas do zapewnij własną realizację. Ponownie, myślę, że to komunikuje wiele o tym, jak programista oczekuje, że kod zostanie użyty. Gdybym pisał zarówno klasy bazowe, jak i implementacyjne i znalazł się w użyciu nowych, poważnie przemyślałbym decyzję, aby nie uczynić metody wirtualną w rodzicu i zadeklarował mój zamiar konkretnie.

 8
Author: tvanfosson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-01 22:20:31

Różnica między słowem kluczowym override i new jest taka, że pierwsze z nich nadpisuje metodę, a następne ukrywa metodę.

Sprawdź folllowing linki, aby uzyskać więcej informacji...

MSDN i Inne

 4
Author: Nescio,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-01 22:11:50
  • new słowo kluczowe służy do ukrywania. - oznacza, że ukrywasz swoją metodę w czasie wykonywania. Wyjście będzie oparte na metodzie klasy bazowej.
  • / Align = "left" / - oznacza, że wywołujesz swoją metodę klasy pochodnej z odniesieniem do klasy bazowej. Wyjście będzie oparte na pochodnej metodzie klasy.
 3
Author: Chetan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-11 15:57:55

Moja wersja wyjaśnienia pochodzi z używania właściwości , aby pomóc zrozumieć różnice.

override to dość proste, prawda ? Typ podstawowy nadpisuje rodzica.

new jest być może mylące (dla mnie było). Z właściwościami łatwiej zrozumieć:

public class Foo
{
    public bool GetSomething => false;
}

public class Bar : Foo
{
    public new bool GetSomething => true;
}

public static void Main(string[] args)
{
    Foo foo = new Bar();
    Console.WriteLine(foo.GetSomething);

    Bar bar = new Bar();
    Console.WriteLine(bar.GetSomething);
}

Używając debugera można zauważyć, że Foo foo ma 2 GetSomething właściwości, ponieważ w rzeczywistości ma 2 wersje właściwości, Foo's i Bar' s, i wiedzieć którego użyć, c# "wybiera" właściwość dla bieżącego typu.

Jeśli chcesz użyć wersji paska, zamiast tego użyłbyś override lub use Foo foo.

Bar bar ma tylko 1, jak chce całkowicie nowe zachowanie dla GetSomething.

 1
Author: Dror Weiss,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-06 07:30:48