Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Il linguaggio C# è progettato in modo che il controllo delle versioni tra classi di base e derivate in librerie diverse possa evolversi e mantenere la compatibilità con le versioni precedenti. Ciò significa, ad esempio, che l'introduzione di un nuovo membro in una classe base con lo stesso nome di un membro in una classe derivata è completamente supportata da C# e non comporta comportamenti imprevisti. Significa anche che una classe deve indicare in modo esplicito se un metodo deve eseguire l'override di un metodo ereditato o se un metodo è un nuovo metodo che nasconde un metodo ereditato denominato in modo analogo.
In C# le classi derivate possono contenere metodi con lo stesso nome dei metodi della classe base.
Se il metodo nella classe derivata non è preceduto da parole chiave new o override , il compilatore genera un avviso e il metodo si comporta come se la
new
parola chiave fosse presente.Se il metodo nella classe derivata è preceduto dalla
new
parola chiave , il metodo viene definito come indipendente dal metodo nella classe base.Se il metodo nella classe derivata è preceduto dalla
override
parola chiave , gli oggetti della classe derivata chiameranno tale metodo anziché il metodo della classe base.Per applicare la
override
parola chiave al metodo nella classe derivata, il metodo della classe base deve essere definito virtuale.Il metodo della classe base può essere chiamato dall'interno della classe derivata usando la
base
parola chiave .Le
override
parole chiave ,virtual
enew
possono essere applicate anche a proprietà, indicizzatori ed eventi.
Per impostazione predefinita, i metodi C# non sono virtuali. Se un metodo viene dichiarato come virtuale, qualsiasi classe che eredita il metodo può implementare la propria versione. Per rendere virtuale un metodo, il virtual
modificatore viene usato nella dichiarazione del metodo della classe base. La classe derivata può quindi eseguire l'override del metodo virtuale di base usando la override
parola chiave o nascondere il metodo virtuale nella classe base usando la new
parola chiave . Se non viene specificata né la override
parola chiave né la new
parola chiave , il compilatore genererà un avviso e il metodo nella classe derivata nasconderà il metodo nella classe base.
Per dimostrare questo problema in pratica, presupporre per un momento che la Società A abbia creato una classe denominata GraphicsClass
, che il programma usa. Quanto segue è GraphicsClass
:
class GraphicsClass
{
public virtual void DrawLine() { }
public virtual void DrawPoint() { }
}
L'azienda usa questa classe e la si usa per derivare la propria classe, aggiungendo un nuovo metodo:
class YourDerivedGraphicsClass : GraphicsClass
{
public void DrawRectangle() { }
}
L'applicazione viene usata senza problemi, fino a quando la Società A non rilascia una nuova versione di GraphicsClass
, simile al codice seguente:
class GraphicsClass
{
public virtual void DrawLine() { }
public virtual void DrawPoint() { }
public virtual void DrawRectangle() { }
}
La nuova versione di GraphicsClass
ora contiene un metodo denominato DrawRectangle
. Inizialmente, non si verifica nulla. La nuova versione è ancora compatibile a livello binario con la versione precedente. Qualsiasi software distribuito continuerà a funzionare, anche se la nuova classe è installata in tali sistemi. Qualsiasi chiamata esistente al metodo DrawRectangle
continuerà a fare riferimento alla tua versione nella classe derivata.
Tuttavia, non appena si ricompila l'applicazione usando la nuova versione di GraphicsClass
, si riceverà un avviso dal compilatore CS0108. Questo avviso ti informa che devi considerare come vuoi che si comporti il metodo DrawRectangle
nella tua applicazione.
Per eseguire l'override del nuovo metodo della classe di base, usare la override
parola chiave :
class YourDerivedGraphicsClass : GraphicsClass
{
public override void DrawRectangle() { }
}
La override
parola chiave assicura che tutti gli oggetti derivati da YourDerivedGraphicsClass
useranno la versione della classe derivata di DrawRectangle
. Gli oggetti derivati da YourDerivedGraphicsClass
possono comunque accedere alla versione della classe base di DrawRectangle
usando la parola chiave base:
base.DrawRectangle();
Se non vuoi che il tuo metodo sostituisca il metodo della classe base, si applicano le seguenti considerazioni. Per evitare confusione tra i due metodi, è possibile rinominare il metodo. Questo può richiedere molto tempo e soggetto a errori e non solo pratico in alcuni casi. Tuttavia, se il progetto è relativamente piccolo, è possibile usare le opzioni di refactoring di Visual Studio per rinominare il metodo. Per altre informazioni, vedere Refactoring di classi e tipi (Progettazione classi).
In alternativa, è possibile impedire l'avviso usando la parola chiave new
nella definizione della classe derivata:
class YourDerivedGraphicsClass : GraphicsClass
{
public new void DrawRectangle() { }
}
L'uso della new
parola chiave indica al compilatore che la definizione nasconde la definizione contenuta nella classe di base. Si tratta del comportamento predefinito.
Eseguire l'override e la selezione del metodo
Quando un metodo viene denominato su una classe, il compilatore C# seleziona il metodo migliore da chiamare se più di un metodo è compatibile con la chiamata, ad esempio quando sono presenti due metodi con lo stesso nome e parametri compatibili con il parametro passato. I metodi seguenti sono compatibili:
public class Derived : Base
{
public override void DoWork(int param) { }
public void DoWork(double param) { }
}
Quando DoWork
viene chiamato su un'istanza di Derived
, il compilatore C# tenterà innanzitutto di rendere la chiamata compatibile con le versioni di DoWork
dichiarate originariamente in Derived
. I metodi di override non vengono considerati dichiarati in una classe, ma sono nuove implementazioni di un metodo dichiarato in una classe base. Solo se il compilatore C# non può corrispondere alla chiamata al metodo a un metodo originale in Derived
, tenterà di associare la chiamata a un metodo sottoposto a override con lo stesso nome e parametri compatibili. Per esempio:
int val = 5;
Derived d = new();
d.DoWork(val); // Calls DoWork(double).
Poiché la variabile val
può essere convertita in modo implicito a un double, il compilatore C# chiama DoWork(double)
anziché DoWork(int)
. Esistono due modi per evitare questo problema. In primo luogo, evitare di dichiarare nuovi metodi con lo stesso nome dei metodi virtuali. In secondo luogo, è possibile indicare al compilatore C# di chiamare il metodo virtuale eseguendo la ricerca nell'elenco dei metodi della classe di base eseguendo il cast dell'istanza di Derived
a Base
. Poiché il metodo è virtuale, verrà chiamata l'implementazione di DoWork(int)
in Derived
. Per esempio:
((Base)d).DoWork(val); // Calls DoWork(int) on Derived.
Per altri esempi di new
e override
, vedere Sapere quando usare override e nuove parole chiave.