Versionsverwaltung mit den Schlüsselwörtern "override" und "new" (C#-Programmierhandbuch)
Die C#-Sprache wurde entwickelt, damit die Versionierung von base- (Basis-) und abgeleiteten Klassen in unterschiedlichen Bibliotheken weiterentwickelt und die Abwärtskompatibilität aufrechterhalten werden kann. Das bedeutet z.B., dass die Einführung eines neuen Members in einer Basisklasse mit demselben Name wie ein Member in einer abgeleiteten Klasse von C# vollständig unterstützt wird und nicht zu unerwartetem Verhalten führt. Das bedeutet auch, dass eine Klasse explizit angeben muss, ob eine Methode für das außer Kraft setzen einer geerbten Methode vorgesehen ist, oder ob eine Methode eine neue Methode ist, die eine Methode mit ähnlichem Namen verbirgt.
In C# können abgeleitete Klassen Methoden mit dem gleichen Namen wie Basisklassen-Methoden enthalten.
Wenn der Methode in der abgeleiteten Klasse nicht die Schlüsselwörter new oder override vorangestellt sind, gibt der Compiler eine Warnung aus, und die Methode verhält sich, als ob das Schlüsselwort
new
vorhanden wäre.Wenn der Methode in der abgeleiteten Klasse das Schlüsselwort
new
vorangestellt ist, wird die Methode als unabhängig von der Methode in der Basisklasse definiert.Wenn der Methode in der abgeleiteten Klasse das Schlüsselwort
override
vorangestellt ist, rufen Objekte der abgeleiteten Klasse diese Methode anstatt der Methode der Basisklasse auf.Um das
override
-Schlüsselwort auf die Methode in der abgeleiteten Klasse anzuwenden, muss die Basisklassenmethode virtuell definiert werden.Die Methode der Basisklasse kann mithilfe des Schlüsselworts
base
aus der Basisklasse heraus aufgerufen werden.Die Schlüsselwörter
override
,virtual
undnew
können auch auf Eigenschaften, Indexer und Ereignisse angewendet werden.
Standardmäßig sind C#-Methoden nicht virtuell. Wenn eine Methode als virtuell deklariert wird, kann jede Klasse, die die Methode erbt, ihre eigene Version implementieren. Um eine Methode in eine virtuelle Methode zu transformieren, wird der Modifizierer virtual
in der Methodendeklaration der Basisklasse verwendet. Die abgeleitete Klasse kann anschließend die virtuelle Methode der Basisklasse mithilfe des Schlüsselworts override
überschreiben oder die virtuelle Methode in der Basisklasse mithilfe des Schlüsselworts new
verbergen. Wenn weder das Schlüsselwort override
noch das Schlüsselwort new
angegeben ist, gibt der Compiler eine Warnung aus, und die Methode in der abgeleiteten Klasse verbirgt die Methode in der Basisklasse.
Nehmen wir zur Veranschaulichung dieser Vorgehensweise für einen Moment an, dass die Firma A eine Klasse mit dem Namen GraphicsClass
erstellt, die Ihr Programm benutzt. Die folgende Datei ist GraphicsClass
:
class GraphicsClass
{
public virtual void DrawLine() { }
public virtual void DrawPoint() { }
}
Ihr Unternehmen verwendet diese Klasse, und Sie verwenden sie zum Ableiten einer Klasse oder zum Hinzufügen einer neuen Methode:
class YourDerivedGraphicsClass : GraphicsClass
{
public void DrawRectangle() { }
}
Ihre Anwendung wird ohne Probleme verwendet, bis Firma A eine neue Version von GraphicsClass
herausgibt, die dem folgenden Code ähnelt:
class GraphicsClass
{
public virtual void DrawLine() { }
public virtual void DrawPoint() { }
public virtual void DrawRectangle() { }
}
Die neue Version von GraphicsClass
enthält jetzt eine Methode namens DrawRectangle
. Anfänglich geschieht nichts. Die neue Version ist immer noch binärkompatibel mit der alten Version. Jede Software, die Sie entwickelt haben, funktioniert weiterhin, sogar wenn die neue Klasse auf diesen Computersystemen installiert ist. Aufgrund vorhandener Aufrufe der Methode verweist DrawRectangle
weiterhin auf Ihre Version in Ihrer abgeleiteten Klasse.
Sobald Sie Ihre Anwendung aber mit der neuen Version von GraphicsClass
neu kompilieren, erhalten Sie vom Compiler eine Warnung, CS0108. Diese Warnung informiert Sie darüber, dass Sie das gewünschte Verhalten der DrawRectangle
-Methode in Ihrer Anwendung bestimmen müssen.
Wenn Sie möchten, dass Ihre Methode die neue Basisklassenmethode außer Kraft setzt, verwenden Sie das Schlüsselwort override
:
class YourDerivedGraphicsClass : GraphicsClass
{
public override void DrawRectangle() { }
}
Das Schlüsselwort override
stellt sicher, dass alle Objekte, die von YourDerivedGraphicsClass
abgeleitet sind, die Version von DrawRectangle
der abgeleiteten Klasse verwenden. Objekte, die von YourDerivedGraphicsClass
abgeleitet sind, können auf die Basisklassenversion von DrawRectangle
mithilfe des base-Schlüsselworts zugreifen:
base.DrawRectangle();
Wenn Sie nicht möchten, dass Ihre Methode die neue Basisklassenmethode außer Kraft setzt, gelten die folgenden Überlegungen. Sie können Ihre Methode umbenennen, um Verwechslungen zwischen den beiden Methoden zu vermeiden. Dies kann zeitaufwändig und fehleranfällig sein und ist in einigen Fällen einfach nicht praktikabel. Wenn das Projekt aber relativ klein ist, können Sie die Refactoring-Optionen von Visual Studio verwenden, um die Methode umzubenennen. Weitere Informationen finden Sie unter Refactoring von Klassen und Typen (Klassen-Designer).
Alternativ können Sie die Warnung vermeiden, indem Sie in der Definition Ihrer abgeleiteten Klasse das Schlüsselwort new
verwenden:
class YourDerivedGraphicsClass : GraphicsClass
{
public new void DrawRectangle() { }
}
Mit dem Schlüsselwort new
teilt der Compiler mit, dass Ihre Definition die Definition ausblendet, die in der Basisklasse enthalten ist. Dies ist das Standardverhalten.
Überschreiben und Methodenauswahl
Wenn eine Methode in einer Klasse benannt wird, wählt der C#-Compiler die beste Methode zum Aufrufen aus, wenn mehr als eine Methode mit dem Aufruf kompatibel ist, z.B. wenn es zwei Methoden mit dem gleichen Namen und Parameter gibt, die mit dem übergebenen Parameter kompatibel sind. Die folgenden Methoden wären kompatibel:
public class Derived : Base
{
public override void DoWork(int param) { }
public void DoWork(double param) { }
}
Wenn DoWork
für eine Instanz von Derived
aufgerufen wird, versucht der C#-Compiler zuerst, den Aufruf mit den Versionen von DoWork
kompatibel zu machen, die ursprünglich für Derived
deklariert wurden. Override-Methoden werden nicht als Methoden angesehen, die für eine Klasse deklariert sind. Stattdessen sind sie neue Implementierungen einer Methode, die für eine Basisklasse deklariert wurde. Nur wenn der C#-Compiler keine Übereinstimmung des Methodenaufrufs mit dem Aufruf einer ursprünglichen Methode in Derived
feststellen kann, versucht er, den Aufruf mit einer überschriebenen Methode mit dem gleichen Namen und kompatiblen Parametern übereinzustimmen. Zum Beispiel:
int val = 5;
Derived d = new Derived();
d.DoWork(val); // Calls DoWork(double).
Da die Variable val
implizit in einen Double-Wert konvertiert werden kann, ruft der C#-Compiler DoWork(double)
anstelle von DoWork(int)
auf. Es gibt zwei Möglichkeiten, das zu vermeiden. Vermeiden Sie zuerst das Deklarieren neuer Methoden mit dem gleichen Namen wie virtuelle Methoden. Zweitens können Sie den C#-Compiler anweisen, die virtuelle Methode aufzurufen, indem Sie eine Suche nach der Liste der Basisklassenmethode durchführen lassen. Dies geschieht durch umwandeln der Instanz von Derived
in Base
. Da es sich um eine virtuelle Methode handelt, wird die Implementierung von DoWork(int)
auf Derived
aufgerufen. Zum Beispiel:
((Base)d).DoWork(val); // Calls DoWork(int) on Derived.
Weitere Beispiele für new
und override
finden Sie unter Wann müssen die Schlüsselwörter „override“ und „new“ verwendet werden?.
Weitere Informationen
Feedback
https://aka.ms/ContentUserFeedback.
Bald verfügbar: Im Laufe des Jahres 2024 werden wir GitHub-Tickets als Feedbackmechanismus für Inhalte auslaufen lassen und es durch ein neues Feedbacksystem ersetzen. Weitere Informationen finden Sie unter:Einreichen und Feedback anzeigen für