Frage

Was ist der Unterschied zwischen einer Methode in einem Basistyp „virtual“ erklärt und überschreibt sie dann in einem Kind Typ des „override“ Schlüsselwort im Gegensatz zu einfach das „new“ Schlüsselwort, wenn die Anpassungsmethode in den Kindern Typ deklariert ?

War es hilfreich?

Lösung

Das „neue“ Schlüsselwort nicht außer Kraft gesetzt, so bedeutet es eine neue Methode, die nichts mit der Basisklasse Methode zu tun hat.

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 ());
    }
}

Dieser druckt falsch, wenn Sie Überschreibung verwendet wird, würde es wahr gedruckt hat.

(Basiscode genommen von Joseph Daigle)

Wenn Sie also echten Polymorphismus tun Sie sollte immer ÜBERSCHREIBEN . Der einzige Ort, wo Sie brauchen, „neu“ zu verwenden ist, wenn das Verfahren nicht in irgendeiner Weise auf die Basisklasse Version verwandt ist.

Andere Tipps

ich immer Dinge wie diese finden leichter mit Bildern zu verstehen:

Auch Joseph Daigle den Code nehmen,

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

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

Wenn Sie dann den Code wie folgt aufrufen:

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

Hinweis: Das Wichtigste ist, dass unser Ziel ist eigentlich ein Bar, aber wir sind es in einer Variablen vom Typ Speichern Foo (ähnlich es dem Gießen)

Dann wird das Ergebnis wie folgt, je nachdem, ob Sie verwendet virtual / override oder new wenn Ihre Klassen deklariert.

Hier ist ein Code, den Unterschied im Verhalten von virtuellen und nicht virtuellen Methoden zu verstehen:

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;
    }
}

Das new Schlüsselwort tatsächlich schafft ein völlig neues Element, das auf diesem spezifischen Typ existiert nur.

Zum Beispiel

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

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

Das Verfahren existiert auf beiden Typen. Wenn Sie Reflexion und erhalten die Mitglieder des Typs Bar verwenden, werden Sie finden tatsächlich zwei Methoden aufgerufen DoSomething(), die gleich genau so aussehen. Durch new Verwendung verstecken Sie effektiv die Umsetzung in der Basisklasse, so dass, wenn Klassen von Bar ableiten (in meinem Beispiel) der Methodenaufruf zu base.DoSomething() Bar und nicht Foo geht.

virtual / Override sagt dem Compiler, dass die beiden Verfahren verbunden sind und dass in einigen Fällen, wenn Sie denken, würden Sie das erste (virtuelle) Methode nennen es tatsächlich richtig ist das zweite zu nennen (außer Kraft gesetzt) Verfahren statt. Dies ist die Grundlage des Polymorphismus.

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

Wird die SubClass nennen überschriebenen VirtualFoo () -Methode.

neue sagt dem Compiler, dass Sie eine Methode einer abgeleiteten Klasse mit dem gleichen Namen wie eine Methode in der Basisklasse hinzufügen, aber sie haben keine Beziehung zueinander stehen.

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

Wird der Baseclass des NewBar () -Methode aufrufen, während:

(new SubClass()).NewBar()

Wird die SubClass der NewBar () -Methode aufrufen.

Darüber hinaus nur die technischen Details, ich denke, mit virtueller / Überschreibung kommuniziert viele semantischen Informationen über das Design. Wenn Sie eine Methode virtuellen deklarieren, geben Sie an, dass Sie erwarten, dass die Umsetzung Klassen wollen können ihre eigenen, nicht-Standardimplementierungen zur Verfügung zu stellen. Das Weglassen dieses in einer Basisklasse, erklärt ebenfalls, die Erwartung, dass die Standardmethode sollte für alle implementierenden Klassen genügen. Ebenso kann man abstrakte Erklärungen verwenden, um die Umsetzung Klassen zu zwingen, ihre eigene Implementierung zur Verfügung zu stellen. Auch ich denke, das viel über in Verbindung steht, wie der Programmierer den Code verwendet werden erwartet. Wenn ich sowohl die Basis zu schreiben und Klassen der Umsetzung und fand mich neu mit Ich würde ernsthaft die Entscheidung überdenken nicht die Methode virtuell in den Eltern zu machen und zu erklären, meine Absicht spezifisch.

Der Unterschied zwischen dem Schlüsselwort override und neuem Schlüsselwort ist, dass erstere tut Methode übergeordnete und die später tut Methode versteckt.

Überprüfen Sie die folllowing Links für weitere Informationen ...

MSDN und Andere

  • new Schlüsselwort ist für das Verstecken. - bedeutet, dass Sie Ihre Methode zur Laufzeit verstecken. Die Ausgabe wird auf Basis Basisklassenmethode werden.
  • override für übergeordnete. - bedeutet, dass Sie Ihre abgeleitete Klasse-Methode mit dem Bezug von Basisklasse aufgerufen wird. Die Ausgabe wird auf abgeleitete Klasse Methode basieren.

Meine Version der Erklärung kommt aus mit Eigenschaften , um die Unterschiede zu verstehen.

override ist einfach genug, nicht wahr? Der zugrunde liegende Typ überschreibt die Eltern.

new ist vielleicht die irreführend (bei mir war es). Mit Eigenschaften ist es einfacher zu verstehen:

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);
}

mit einem Debugger können Sie diese Foo foo bemerken hat 2 GetSomething Eigenschaften, wie es tatsächlich zwei Versionen der Eigenschaft, Foo der und Bar der, und die man zu verwenden, c # „nimmt“ kennen die Eigenschaft für den aktuellen Typ.

Wenn Sie die Bar-Version nutzen wollten, würden Sie überschreiben oder die Verwendung Foo foo stattdessen verwendet haben.

Bar bar hat nur 1 , da es vollständig neue Verhalten für GetSomething will.

Nicht ein Verfahren mit etwas Markierung bedeutet: Binden Sie diese Methode der Kompilierung Typ des Objekts verwenden, nicht Laufzeittyp (statische Bindung).

ein Verfahren mit virtual Markierung bedeutet: diese Methode binden die Laufzeittyp des Objekts verwenden, keine Zeit Typ kompilieren (dynamische Bindung).

eine Basisklasse virtual Methode mit override in abgeleiteten Klasse Markierungsmittel: Dieses Verfahren ist das Objekt, das Laufzeittyp (dynamische Bindung) gebunden sein zu verwenden.

eine Basisklasse virtual Methode mit new in abgeleiteten Klasse Kennzeichnung bedeutet: Dies ist eine neue Methode, die in der Basisklasse in kein Verhältnis zu dem mit dem gleichen Namen hat, und es soll Typen der Kompilierung mit Objekt gebunden wird (statische Bindung ).

keine Basisklasse virtual Methode in der abgeleiteten Klasse Markierungsmittel: Diese Methode wie new (statische Bindung) gekennzeichnet ist.

ein Verfahren abstract Markierung bedeutet: Diese Methode ist virtuell, aber ich werde nicht einen Körper für ihn und seine Klasse deklarieren ist auch abstrakt (dynamische Bindung).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top