Questa è una domanda sui metodi di estensione di C # e sulla loro filosofia di progettazione, quindi penso che il modo migliore per rispondere a questa domanda sia di citare la documentazione di MSDN sullo scopo dei metodi di estensione :
I metodi di estensione consentono di "aggiungere" metodi a tipi esistenti senza creare un nuovo tipo derivato, ricompilare o modificare in altro modo il tipo originale. I metodi di estensione sono un tipo speciale di metodo statico, ma vengono chiamati come se fossero metodi di istanza sul tipo esteso. Per il codice client scritto in C #, F # e Visual Basic, non esiste alcuna differenza apparente tra la chiamata di un metodo di estensione e i metodi che sono effettivamente definiti in un tipo.
...
In generale, si consiglia di implementare i metodi di estensione con parsimonia e solo quando è necessario. Quando possibile, il codice client che deve estendere un tipo esistente dovrebbe farlo creando un nuovo tipo derivato dal tipo esistente. Per ulteriori informazioni, vedere Ereditarietà.
Quando si utilizza un metodo di estensione per estendere un tipo di cui non è possibile modificare il codice sorgente, si corre il rischio che una modifica dell'implementazione del tipo causi l'interruzione del metodo di estensione.
Se si implementano metodi di estensione per un determinato tipo, tenere presente i seguenti punti:
- Un metodo di estensione non verrà mai chiamato se ha la stessa firma di un metodo definito nel tipo.
- I metodi di estensione vengono portati nell'ambito a livello di spazio dei nomi. Ad esempio, se si hanno più classi statiche che contengono metodi di estensione in un singolo spazio dei nomi denominato
Extensions
, saranno tutti inclusi nell'ambito della using Extensions;
direttiva.
Per riassumere, i metodi di estensione sono progettati per aggiungere metodi di istanza a un tipo particolare, anche quando gli sviluppatori non possono farlo direttamente. E poiché i metodi di istanza sovrascriveranno sempre i metodi di estensione se presenti (se chiamati usando la sintassi del metodo di istanza), questo dovrebbe essere fatto solo se non è possibile aggiungere direttamente un metodo o estendere la classe. *
In altre parole, un metodo di estensione dovrebbe agire esattamente come farebbe un metodo di istanza, perché potrebbe finire per diventare un metodo di istanza da alcuni client. E poiché un metodo di istanza dovrebbe essere lanciato se l'oggetto su cui viene chiamato è null
, così dovrebbe essere il metodo di estensione.
* Come nota a margine, questa è esattamente la situazione che i progettisti di LINQ hanno affrontato: quando è stato rilasciato C # 3.0, c'erano già milioni di clienti che stavano usando System.Collections.IEnumerable
e System.Collections.Generic.IEnumerable<T>
, sia nelle loro collezioni che nei foreach
loop. Queste classi restituiti IEnumerator
oggetti che avevano solo i due metodi Current
e MoveNext
, quindi aggiungendo eventuali metodi di istanza richieste addizionali, come Count
, Any
ecc, sarebbe rompendo questi milioni di clienti. Quindi, al fine di fornire questa funzionalità (soprattutto perché può essere implementata in termini diCurrent
e MoveNext
con relativa facilità), l'hanno rilasciata come metodo di estensione, che può essere applicato a qualsiasi attualmente esistenteIEnumerable
istanza e può anche essere implementato dalle classi in modi più efficienti. Se i progettisti di C # avessero deciso di rilasciare LINQ dal primo giorno, sarebbe stato fornito come metodo di istanza diIEnumerable
e probabilmente avrebbero progettato un qualche tipo di sistema per fornire implementazioni di interfaccia predefinite di tali metodi.