Versiebeheer met de onderdrukking en nieuwe trefwoorden (C#-programmeerhandleiding)

De C#-taal is zodanig ontworpen dat versiebeheer tussen basis - en afgeleide klassen in verschillende bibliotheken kan evolueren en achterwaartse compatibiliteit kunnen behouden. Dit betekent bijvoorbeeld dat de introductie van een nieuw lid in een basisklasse met dezelfde naam als een lid in een afgeleide klasse volledig wordt ondersteund door C# en niet leidt tot onverwacht gedrag. Het betekent ook dat een klasse expliciet moet aangeven of een methode is bedoeld om een overgenomen methode te overschrijven of dat een methode een nieuwe methode is die een vergelijkbare overgenomen methode verbergt.

In C# kunnen afgeleide klassen methoden bevatten met dezelfde naam als basisklassemethoden.

  • Als de methode in de afgeleide klasse niet wordt voorafgegaan door nieuwe trefwoorden of trefwoorden overschrijven , geeft de compiler een waarschuwing uit en gedraagt de methode zich alsof het new trefwoord aanwezig is.

  • Als de methode in de afgeleide klasse voorafgaat aan het new trefwoord, wordt de methode gedefinieerd als onafhankelijk van de methode in de basisklasse.

  • Als de methode in de afgeleide klasse wordt voorafgegaan door het override trefwoord, roepen objecten van de afgeleide klasse die methode aan in plaats van de basisklassemethode.

  • Als u het override trefwoord wilt toepassen op de methode in de afgeleide klasse, moet de basisklassemethode virtueel worden gedefinieerd.

  • De basisklassemethode kan worden aangeroepen vanuit de afgeleide klasse met behulp van het base trefwoord.

  • De override, virtualen new trefwoorden kunnen ook worden toegepast op eigenschappen, indexeerfuncties en gebeurtenissen.

C#-methoden zijn standaard niet virtueel. Als een methode als virtueel wordt gedeclareerd, kan elke klasse die de methode overneemt, een eigen versie implementeren. Als u een methode virtueel wilt maken, wordt de virtual modifier gebruikt in de methodedeclaratie van de basisklasse. De afgeleide klasse kan vervolgens de virtuele basismethode overschrijven door het override trefwoord te gebruiken of de virtuele methode in de basisklasse te verbergen met behulp van het new trefwoord. Als noch het override trefwoord noch het new trefwoord is opgegeven, geeft de compiler een waarschuwing en verbergt de methode in de afgeleide klasse de methode in de basisklasse.

Als u dit in de praktijk wilt demonstreren, gaat u ervan uit dat bedrijf A een klasse heeft gemaakt met de naam GraphicsClass, die door uw programma wordt gebruikt. Het volgende is GraphicsClass:

class GraphicsClass
{
    public virtual void DrawLine() { }
    public virtual void DrawPoint() { }
}

Uw bedrijf gebruikt deze klasse en u gebruikt deze om uw eigen klasse af te leiden en een nieuwe methode toe te voegen:

class YourDerivedGraphicsClass : GraphicsClass
{
    public void DrawRectangle() { }
}

Uw toepassing wordt zonder problemen gebruikt, totdat bedrijf A een nieuwe versie van GraphicsClass, die lijkt op de volgende code:

class GraphicsClass
{
    public virtual void DrawLine() { }
    public virtual void DrawPoint() { }
    public virtual void DrawRectangle() { }
}

De nieuwe versie van GraphicsClass nu bevat een methode met de naam DrawRectangle. In eerste instantie gebeurt er niets. De nieuwe versie is nog steeds binair compatibel met de oude versie. Alle software die u hebt geïmplementeerd, blijft werken, zelfs als de nieuwe klasse op deze computersystemen is geïnstalleerd. Eventuele bestaande aanroepen naar de methode DrawRectangle blijven verwijzen naar uw versie in uw afgeleide klasse.

Zodra u uw toepassing echter opnieuw compileeert met behulp van de nieuwe versie van GraphicsClass, ontvangt u een waarschuwing van de compiler CS0108. Deze waarschuwing informeert u dat u rekening moet houden met de manier waarop uw methode zich in uw toepassing moet DrawRectangle gedragen.

Als u wilt dat uw methode de nieuwe basisklassemethode overschrijft, gebruikt u het override trefwoord:

class YourDerivedGraphicsClass : GraphicsClass
{
    public override void DrawRectangle() { }
}

Het override trefwoord zorgt ervoor dat objecten die zijn afgeleid van YourDerivedGraphicsClass de afgeleide klasseversie van DrawRectangle. Objecten die zijn afgeleid van YourDerivedGraphicsClass , hebben nog steeds toegang tot de basisklasseversie van DrawRectangle het basiswoord:

base.DrawRectangle();

Als u niet wilt dat uw methode de nieuwe basisklassemethode overschrijft, zijn de volgende overwegingen van toepassing. Om verwarring tussen de twee methoden te voorkomen, kunt u de naam van uw methode wijzigen. Dit kan tijdrovend en foutgevoelig zijn, en in sommige gevallen niet praktisch. Als uw project echter relatief klein is, kunt u de herstructureringsopties van Visual Studio gebruiken om de naam van de methode te wijzigen. Zie Klassen en typen herstructureren (Class Designer) voor meer informatie.

U kunt de waarschuwing ook voorkomen met behulp van het trefwoord new in de definitie van uw afgeleide klasse:

class YourDerivedGraphicsClass : GraphicsClass
{
    public new void DrawRectangle() { }
}

Met behulp van het new trefwoord vertelt de compiler dat uw definitie de definitie verbergt die zich in de basisklasse bevindt. Dit is het standaardgedrag.

Onderdrukking en methodeselectie

Wanneer een methode een naam heeft voor een klasse, selecteert de C#-compiler de beste methode om aan te roepen als meer dan één methode compatibel is met de aanroep, zoals wanneer er twee methoden met dezelfde naam zijn en parameters die compatibel zijn met de doorgegeven parameter. De volgende methoden zijn compatibel:

public class Derived : Base
{
    public override void DoWork(int param) { }
    public void DoWork(double param) { }
}

Wanneer DoWork wordt aangeroepen op een exemplaar van Derived, probeert de C#-compiler eerst de aanroep compatibel te maken met de versies van DoWork gedeclareerd die oorspronkelijk zijn gedeclareerd Derived. Onderdrukkingsmethoden worden niet beschouwd als gedeclareerd op een klasse. Dit zijn nieuwe implementaties van een methode die is gedeclareerd op een basisklasse. Alleen als de C#-compiler niet overeenkomt met de methodeaanroep naar een oorspronkelijke methode Derived, wordt geprobeerd de aanroep te koppelen aan een overschreven methode met dezelfde naam en compatibele parameters. Voorbeeld:

int val = 5;
Derived d = new Derived();
d.DoWork(val);  // Calls DoWork(double).

Omdat de variabele val impliciet kan worden geconverteerd naar een dubbele, roept de C#-compiler DoWork(double) aan in plaats van DoWork(int). Er zijn twee manieren om dit te voorkomen. Vermijd eerst het declareren van nieuwe methoden met dezelfde naam als virtuele methoden. Ten tweede kunt u de C#-compiler instrueren om de virtuele methode aan te roepen door de lijst met basisklassemethoden te doorzoeken door het exemplaar van Derived naar .Base Omdat de methode virtueel is, wordt de implementatie van DoWork(int) aangeroepen Derived . Voorbeeld:

((Base)d).DoWork(val);  // Calls DoWork(int) on Derived.

Zie Weten wanneer u onderdrukking en nieuwe trefwoorden moet gebruiken voor meer voorbeelden van new enoverride.

Zie ook