webentwicklung-frage-antwort-db.com.de

Unterschied zwischen Neu und Überschreiben

Frage mich, was der Unterschied zwischen den folgenden ist:

Fall 1: Basisklasse

public void DoIt();

Fall 1: Vererbte Klasse 

public new void DoIt();

Fall 2: Basisklasse

public virtual void DoIt();

Fall 2: Vererbte Klasse 

public override void DoIt();

Fall 1 und 2 scheinen die gleichen Auswirkungen zu haben, basierend auf den von mir durchgeführten Tests. Gibt es einen Unterschied oder einen bevorzugten Weg?

164
Shiraz Bhaiji

Der Überschreibungsmodifizierer kann für .__ verwendet werden. virtuelle Methoden und müssen auf .__ verwendet werden. abstrakte Methoden. Dies bedeutet für Der Compiler verwendet die zuletzt definierte Implementierung einer Methode. Selbst wenn Die Methode wird für einen Verweis auf .__ aufgerufen. Die Basisklasse verwendet die Implementierung überschreiben.

public class Base
{
    public virtual void DoIt()
    {
    }
}

public class Derived : Base
{
    public override void DoIt()
    {
    }
}

Base b = new Derived();
b.DoIt();                      // Calls Derived.DoIt

ruft Derived.DoIt auf, wenn dies Base.DoIt überschreibt.

Der neue Modifikator weist die .__ an. Compiler zur Verwendung der Implementierung der Kindklasse anstelle der übergeordneten Klasse Implementierung. Jeder Code, der nicht .__ ist. Verweist auf Ihre Klasse, aber auf das übergeordnete Element Klasse verwendet die übergeordnete Klasse Implementierung.

public class Base
{
    public virtual void DoIt()
    {
    }
}

public class Derived : Base
{
    public new void DoIt()
    {
    }
}

Base b = new Derived();
Derived d = new Derived();

b.DoIt();                      // Calls Base.DoIt
d.DoIt();                      // Calls Derived.DoIt

Ruft zuerst Base.DoIt und dann Derived.DoIt auf. Es handelt sich tatsächlich um zwei völlig getrennte Methoden, die zufällig denselben Namen haben, und nicht die abgeleitete Methode, die die Basismethode überschreibt.

Quelle: Microsoft-Blog

220
rahul

virtual : Gibt an, dass eine Methode möglicherweise von einem Erben überschrieben wird

override : überschreibt die Funktionalität einer virtuellen Methode in einer Basisklasse und stellt unterschiedliche Funktionen bereit.

new : verbirgt die ursprüngliche Methode (die nicht virtuell sein muss) und bietet unterschiedliche Funktionen. Dies sollte nur verwendet werden, wo es absolut notwendig ist.

Wenn Sie eine Methode ausblenden, können Sie immer noch auf die ursprüngliche Methode zugreifen, indem Sie eine Umwandlung in die Basisklasse durchführen. Dies ist in einigen Szenarien hilfreich, aber gefährlich.

162
Jon B

Im ersten Fall verbergen Sie die Definition in der übergeordneten Klasse. Dies bedeutet, dass es nur aufgerufen wird, wenn Sie das Objekt als untergeordnete Klasse behandeln. Wenn Sie die Klasse in ihren übergeordneten Typ umwandeln, wird die Methode des übergeordneten Elements aufgerufen. Im zweiten Fall wird die Methode überschrieben und unabhängig davon, ob das Objekt als untergeordnete Klasse oder als übergeordnete Klasse umgewandelt wird, aufgerufen.

14
tvanfosson

versuchen Sie folgendes: (Fall1)

((BaseClass)(new InheritedClass())).DoIt()

Edit: virtual + override werden zur Laufzeit aufgelöst (überschreibt also wirklich virtuelle Methoden), während new nur eine neue Methode mit demselben Namen erstellt und die alte versteckt, sie wird zur Kompilierzeit aufgelöst -> Ihr Compiler ruft die Methode ' sieht '

7
nothrow

Der Unterschied zwischen den beiden Fällen ist, dass im Fall 1 die DoIt-Basismethode nicht überschrieben, sondern nur ausgeblendet wird. Dies bedeutet, dass abhängig vom Typ der Variablen davon abhängt, welche Methode aufgerufen wird. Zum Beispiel:

BaseClass instance1 = new SubClass();
instance1.DoIt(); // Calls base class DoIt method

SubClass instance2 = new SubClass();
instance2.DoIt(); // Calls sub class DoIt method

Dies kann sehr verwirrend sein und zu nicht erwartetem Verhalten führen und sollte nach Möglichkeit vermieden werden. Der bevorzugte Weg wäre also Fall 2.

3
Shannon Cornish

Wenn Sie die DoIt () - Methode der geerbten Klasse aufgerufen haben, während der Typ als Basisklasse deklariert ist, wird die Aktion der Basisklasse sogar angezeigt.

/* Results
Class1
Base1
Class2
Class2
*/
public abstract class Base1
{
    public void DoIt() { Console.WriteLine("Base1"); }
}
public  class Class1 : Base1 
{
    public new void DoIt() { Console.WriteLine("Class1"); }
}
public abstract class Base2
{
    public virtual void DoIt() { Console.WriteLine("Base2"); }
}
public class Class2 : Base2
{
    public override void DoIt() { Console.WriteLine("Class2"); }
}
static void Main(string[] args)
{
    var c1 = new Class1();
    c1.DoIt();
    ((Base1)c1).DoIt();

    var c2 = new Class2();
    c2.DoIt();
    ((Base2)c2).DoIt();
    Console.Read();
}
3
Matthew Whited

Meine Art, beide Schlüsselwörter im Hinterkopf zu behalten, sind sie einander gegenüber.

override: Das Schlüsselwort virtual muss definiert werden, um die Methode zu überschreiben. Die Methode verwendet das Schlüsselwort override, das unabhängig vom Referenztyp (Referenz der Basisklasse oder abgeleiteten Klasse), wenn es mit der Basisklasse instanziiert wird, die Methode der Basisklasse ausführt. Andernfalls wird die Methode der abgeleiteten Klasse ausgeführt.

new: Wenn das Schlüsselwort von einer Methode verwendet wird, ist im Gegensatz zum Schlüsselwort override der Referenztyp wichtig. Wenn es mit abgeleiteten Klassen instanziiert wird und der Referenztyp Basisklasse ist, wird die Methode der Basisklasse ausgeführt. Wenn es mit abgeleiteter Klasse instanziiert wird und der Referenztyp abgeleitete Klasse ist, wird die Methode der abgeleiteten Klasse ausgeführt. Es ist nämlich ein Kontrast von override Schlüsselwort. Wenn Sie vergessen, das neue Schlüsselwort zur Methode hinzuzufügen, verhält sich der Compiler standardmäßig als new-Schlüsselwort.

class A 
{
    public string Foo() 
    {
        return "A";
    }

    public virtual string Test()
    {
        return "base test";
    }
}

class B: A
{
    public new string Foo() 
    {
        return "B";
    }
}

class C: B 
{
    public string Foo() 
    {
        return "C";
    }

    public override string Test() {
        return "derived test";
    }
}

Anrufen in main:

A AClass = new B();
Console.WriteLine(AClass.Foo());
B BClass = new B();
Console.WriteLine(BClass.Foo());
B BClassWithC = new C();
Console.WriteLine(BClassWithC.Foo());

Console.WriteLine(AClass.Test());
Console.WriteLine(BClassWithC.Test());

Ausgabe:

A
B
B
base test
derived test
2
snr

Unter all diesen ist new am verwirrendsten. Durch Experimentieren ist das neue Schlüsselwort so, als würde der Entwickler die Option erhalten, die erbende Klassenimplementierung mit der Basisklassenimplementierung zu überschreiben, indem der Typ explizit definiert wird. Es ist, als würde man anders herum denken. 

Im folgenden Beispiel gibt das Ergebnis "Abgeleitetes Ergebnis" zurück, bis der Typ explizit als BaseClass-Test definiert ist. Nur das "Basisergebnis" wird zurückgegeben.

class Program
{
    static void Main(string[] args)
    {
        var test = new DerivedClass();
        var result = test.DoSomething();
    }
}

class BaseClass
{
    public virtual string DoSomething()
    {
        return "Base result";
    }
}

class DerivedClass : BaseClass
{
    public new string DoSomething()
    {
        return "Derived result";
    }
}
1
usefulBee

Der folgende Artikel ist in vb.net, aber ich denke, die Erklärung der neuen vs-Überschreibungen ist sehr leicht zu verstehen.

https://www.codeproject.com/articles/17477/the-dark-shadow-of-overrides

Irgendwann im Artikel gibt es diesen Satz:

Im Allgemeinen nimmt Shadows an, dass die mit dem Typ verknüpfte Funktion .__ ist. wird aufgerufen, während Überschreibungen davon ausgehen, dass die Objektimplementierung .__ ist. hingerichtet.

Die akzeptierte Antwort auf diese Frage ist perfekt, aber ich denke, dieser Artikel liefert gute Beispiele, um die Unterschiede zwischen diesen beiden Keywords besser zu verstehen.

1
Samuel

Wenn das Schlüsselwort override in der abgeleiteten Klasse verwendet wird, wird die übergeordnete Methode überschrieben.

Wenn das Schlüsselwort new in der abgeleiteten Klasse verwendet wird, leiten Sie die von der übergeordneten Methode verborgene Methode ab.

1
saba

Im ersten Fall wird die abgeleitete Klasse DoIt () -Methode aufgerufen, da das neue Schlüsselwort die DoIt () -Methode der Basisklasse verbirgt.

Im zweiten Fall wird DoIt () überschreiben aufgerufen. 

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

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

public class C : A
{
    public override void DoIt()
    {
        Console.WriteLine("C::DoIt()");
    }
}

instanz dieser Klassen erstellen lassen

   A instanceA = new A();

    B instanceB = new B();
    C instanceC = new C();

    instanceA.DoIt(); //A::DoIt()
    instanceB.DoIt(); //B::DoIt()
    instanceC.DoIt(); //B::DoIt()

Alles wird oben erwartet. Setzen Sie instanceB und instanceC auf instanceA, rufen Sie die Methode DoIt () auf und überprüfen Sie das Ergebnis.

    instanceA = instanceB;
    instanceA.DoIt(); //A::DoIt() calls DoIt method in class A

    instanceA = instanceC;
    instanceA.DoIt();//C::DoIt() calls DoIt method in class C because it was overriden in class C
0
cimey

Der funktionale Unterschied wird in diesen Tests nicht gezeigt:

BaseClass bc = new BaseClass();

bc.DoIt();

DerivedClass dc = new DerivedClass();

dc.ShowIt();

In diesem Beispiel ist das Doit, das aufgerufen wird, das, von dem Sie erwarten, dass es aufgerufen wird.

Um den Unterschied zu sehen, müssen Sie Folgendes tun:

BaseClass obj = new DerivedClass();

obj.DoIt();

Wenn Sie diesen Test ausführen, werden Sie feststellen, dass in Fall 1 (wie Sie ihn definiert haben) DoIt() in BaseClass aufgerufen wird, in Fall 2 (wie von Ihnen definiert) wird DoIt() in DerivedClass aufgerufen. 

0
Ken Falk

Ich hatte die gleiche Frage und es ist wirklich verwirrend. Sie sollten bedenken, dass die Schlüsselwörter override und new nur mit Objekten vom Typ Basisklasse und Wert der abgeleiteten Klasse funktionieren. In diesem Fall sehen Sie nur den Effekt von override und new: Wenn Sie also class A und B haben, B von A erbt, dann instantiieren Sie ein Objekt wie folgt:

A a = new B();

Beim Aufruf von Methoden wird nun der Status berücksichtigtOverride: Bedeutet, dass die Funktion der Methode erweitert wird, dann wird die Methode in der abgeleiteten Klasse verwendet, während new den Compiler dazu auffordert Blenden Sie die Methode in der abgeleiteten Klasse aus und verwenden Sie stattdessen die Methode in der Basisklasse .. Hier ist ein sehr guter Anblick für dieses Thema:

https://msdn.Microsoft.com/DE/library/ms173153%28v=VS.140,d=hv.2%29.aspx?f=255&MSPPError=-2147217396

0
user4451265