Quali vantaggi hai riscontrato dei metodi di estensione? [chiuso]


84

Un "non credente" di C # mi chiedeva quale fosse lo scopo dei metodi di estensione. Ho spiegato che potresti quindi aggiungere nuovi metodi agli oggetti che erano già definiti, specialmente quando non possiedi / controlli la sorgente dell'oggetto originale.

Ha tirato fuori "Perché non aggiungere un metodo alla tua classe?" Abbiamo girato e rigirato (in senso positivo). La mia risposta generale è che è un altro strumento nella cintura degli strumenti, e la sua risposta è che è un inutile spreco di uno strumento ... ma ho pensato di ottenere una risposta più "illuminata".

Quali sono alcuni scenari in cui hai utilizzato metodi di estensione che non avresti potuto (o non avresti dovuto) utilizzare un metodo aggiunto alla tua classe?


2
Penso che ci siano punti decisamente validi che le persone possono fare (e hanno fatto) a sostegno dei metodi di estensione ... ma non c'è sicuramente nessuno scenario in cui uno " non avrebbe potuto" utilizzare metodi statici al posto dei metodi di estensione. I metodi di estensione sono in realtà solo metodi statici, accessibili in modo diverso. Solo qualcosa da tenere a mente.
Dan Tao,

@DanTao, in una nota più leggera, l'unica cosa che rende insostituibile la chiamata per metodo di estensione è la loro stessa denominazione. Extensions.To(1, 10)è privo di significato ed 1.To(10)è descrittivo. Ovviamente capisco il lato tecnico di cui stai parlando, solo dicendo. In effetti ci sono scenari in cui uno " non avrebbe potuto" utilizzare l'approccio di estensione al posto di metodi statici, ad esempio la riflessione, un altro caso è dynamic.
nawfal

Risposte:


35

Penso che i metodi di estensione siano di grande aiuto durante la scrittura di codice, se aggiungi metodi di estensione ai tipi di base li otterrai rapidamente nell'intellisense.

Ho un fornitore di formati per formattare una dimensione di file . Per usarlo devo scrivere:

Console.WriteLine(String.Format(new FileSizeFormatProvider(), "{0:fs}", fileSize));

Creando un metodo di estensione posso scrivere:

Console.WriteLine(fileSize.ToFileSize());

Più pulito e più semplice.


4
un nome più descrittivo per il metodo di estensione lo renderebbe ancora più pulito. ad esempio fileSize.ToFormattedString ();
David Alpert,

1
mmm, ToFormattedFizeSize () forse, è un metodo di estensione per un tipo Long, ToFormattedString () non è un nome descrittivo
Eduardo Campañó

3
punto fatto, però. quando leggo fileSize.ToFileSize () chiedo perché la duplicazione? cosa sta facendo effettivamente? so che è solo un esempio, ma i nomi descrittivi aiutano a renderlo pulito e semplice.
David Alpert,

1
hai ragione perché con i test è molto importante scegliere il nome giusto
Eduardo Campañó

5
Tuttavia, questo non risponde direttamente alla domanda, poiché l'esempio che hai fornito non deve essere un metodo di estensione. Avresti potuto averlo LongToFileSize(fileSize), il che è altrettanto conciso e probabilmente altrettanto chiaro.
Dan Tao,

83

L' unico vantaggio dei metodi di estensione è la leggibilità del codice. Questo è tutto.

I metodi di estensione ti consentono di fare questo:

foo.bar();

Invece di questo:

Util.bar(foo);

Ora ci sono molte cose in C # che sono così. In altre parole, ci sono molte funzionalità in C # che sembrano banali e non hanno grandi vantaggi in sé e per sé. Tuttavia, una volta che inizi a combinare queste caratteristiche insieme, inizi a vedere qualcosa di appena un po 'più grande della somma delle sue parti. LINQ trae grandi vantaggi dai metodi di estensione poiché le query LINQ sarebbero quasi illeggibili senza di essi. LINQ sarebbe possibile senza metodi di estensione, ma non pratico.

I metodi di estensione sono molto simili alle classi parziali di C #. Di per sé non sono molto utili e sembrano banali. Ma quando inizi a lavorare con una classe che necessita di codice generato, le classi parziali iniziano ad avere molto più senso.


1
Questo diventa ancora più importante se stai usando metodi concatenati come x.Foo (something) .Bar (somethingelse) .Baz (yetmoresomething). Questo è più diffuso nei metodi di estensione IEnumerable <> e aumenta significativamente la leggibilità
ShuggyCoUk

2
La cosa che non capisco è che foo.bar () mi suggerisce che bar () è un metodo di foo. Quindi quando non funziona finisco per cercare nel posto sbagliato. Non sono sicuro che questo sia effettivamente un miglioramento della leggibilità per me.
Martin Brown,

3
Fare clic con il pulsante destro del mouse sulla barra () in VS IDE e scegliere Vai alla definizione ti porterebbe nel posto giusto.
Jeff Martin,

9
L'unico vantaggio del 98% dei costrutti del linguaggio è la leggibilità del codice. Tutto ciò che oltre a operatore di filiale, etichetta, goto e incremento è lì per semplificarti la vita.
Giovanni Galbo

2
Non è del tutto vero, in alcune situazioni i metodi di estensione sono l' unico modo per estendere una classe. Oltre alle classi sigillate, le uso in una situazione piuttosto unica. Vedi il mio post qui sotto.
Edwin Jarvis

34

Non dimenticare gli utensili! Quando aggiungi un metodo di estensione M sul tipo Foo, ottieni "M" nell'elenco dell'intellisense di Foo (supponendo che la classe di estensione sia nell'ambito). Questo rende 'M' molto più facile da trovare rispetto a MyClass.M (Foo, ...).

Alla fine della giornata, è solo zucchero sintattico per metodi statici altrove, ma come comprare una casa: "posizione, posizione, posizione!" Se si blocca sul tipo, le persone lo troveranno!


2
C'è anche un leggero aspetto negativo in questo: i metodi di estensione (come quelli di System.Linq riempiono il completamento automatico di IntelliSense con un elenco più lungo, rendendo un po 'più difficile la navigazione.
Jared Updike

@ Jared: ... ma solo se hai importato lo spazio dei nomi in cui risiedono i metodi di estensione, quindi hai effettivamente un piccolo grado di controllo su questo "inquinamento IntelliSense". Secondo, non dimentichiamo che ci sono classi nella BCL (come String) che vengono fornite con un elenco abbastanza lungo di metodi di istanza, quindi questo problema non è specifico dei metodi di estensione.
stakx - non contribuisce più il

29

Altri due vantaggi dei metodi di estensione che ho riscontrato:

  • Un'interfaccia fluente può essere incapsulata in una classe statica di metodi di estensione, ottenendo così una separazione delle preoccupazioni tra la classe principale e le sue estensioni fluenti; Ho visto che ottengono una maggiore manutenibilità.
  • I metodi di estensione possono essere appesi alle interfacce, consentendo in tal modo di specificare un contratto (tramite un'interfaccia) e una serie associata di comportamenti basati sull'interfaccia (tramite metodi di estensione), offrendo ancora una volta una separazione delle preoccupazioni. Un esempio sono l'estensione Linq metodi come Select(...), Where(...)ecc Hung largo della IEnumerable<T>interfaccia.

1
Puoi citare alcuni esempi di codice per entrambi i punti per aiutarli a capire meglio? Sembra essere un punto di vista interessante.
RBT

sì, un esempio per il 2 ° punto sarebbe carino.
Ini

26

Alcuni dei migliori usi che ho avuto per i metodi di estensione sono la capacità di:

  1. Estendi funzionalità su oggetti di terze parti (sia commerciali che interni alla mia azienda ma gestiti da un gruppo separato), che in molti casi saranno contrassegnati come sealed.
  2. Crea funzionalità predefinite per le interfacce senza dover implementare una classe astratta

Prendiamo ad esempio IEnumerable<T>. Sebbene sia ricco di metodi di estensione, ho trovato fastidioso che non implementasse un metodo ForEach generico. Quindi, ho creato il mio:

public void ForEach<T>(this IEnumerable<T> enumerable, Action<T> action)
{
    foreach ( var o in enumerable )
    {
        action(o);
    }
}

Voilà, tutti i miei IEnumerable<T>oggetti indipendentemente dal tipo di implementazione e se l'ho scritto o meno o qualcun altro ora aveva un ForEachmetodo aggiungendo un'appropriata istruzione "using" nel mio codice.


3
+1 Adoro questa estensione, ne ho scritta una proprio simile. Quindi molto utile
Maslow

10
Nota che il metodo deve essere statico. Suggerisco di leggere blogs.msdn.com/ericlippert/archive/2009/05/18/… prima di decidere di utilizzare questa estensione.
TrueWill

Motivo per cui l'implementazione del metodo di estensione ForEach su IEnumerable non è apprezzata: blogs.msdn.microsoft.com/ericlippert/2009/05/18/…
RBT

12

Uno degli ottimi motivi per utilizzare i metodi di estensione è LINQ. Senza i metodi di estensione, molto di ciò che puoi fare in LINQ sarebbe molto difficile. I metodi di estensione Where (), Contains (), Select indicano che molte più funzionalità vengono aggiunte ai tipi esistenti senza modificarne la struttura.


4
non è "uno di", è IL motivo per i metodi di estensione.
gbjbaanb

3
Come mai? È uno dei tanti motivi per avere metodi di estensione, non l'unico requisito. Posso usare metodi di estensione senza usare LINQ.
Ray Booysen

Penso che volesse dire che era il motivo per cui sono stati creati, ma sì, fa sembrare che siano l'unico uso corretto per loro.
Brent Rittenhouse

9

Ci sono molte risposte sui vantaggi dei metodi di estensione; che ne dici di affrontare gli svantaggi ?

Il più grande svantaggio è che non ci sono errori o avvisi del compilatore se si dispone di un metodo normale e di un metodo di estensione con la stessa firma nello stesso contesto.

Supponi di creare un metodo di estensione che si applica a una particolare classe. Successivamente qualcuno crea un metodo con una firma identica su quella classe stessa.

Il tuo codice verrà compilato e potresti non ricevere nemmeno un errore di runtime. Ma non stai più eseguendo lo stesso codice di prima.


1
4. Pensaci due volte prima di estendere i tipi che non possiedi . Se scrivi solo metodi di estensione per i tipi che possiedi, non devi mai preoccuparti che le tue estensioni vengano interrotte dalle modifiche al tipo che viene esteso. D'altra parte, se stai estendendo i tipi di altre persone di quello che sei essenzialmente alla loro mercé.
DavidRR

1
... In alternativa, è possibile ridurre al minimo questo rischio scegliendo nomi che è improbabile che vengano utilizzati da qualcun altro o riducendo al minimo il numero totale di metodi di estensione definiti (ovvero riducendo la superficie). Una tecnica per eseguire questa operazione potrebbe essere quella di scrivere un metodo di estensione che converta l'oggetto sottostante in un tipo diverso controllato dall'utente.
DavidRR

Metodi di estensione (Guida per programmatori C #) : in generale, probabilmente chiamerai metodi di estensione molto più spesso che implementarne uno tuo.
DavidRR


4

Il mio argomento personale per i metodi di estensione è che si adattano molto bene a un progetto OOP: considera il metodo semplice

bool empty = String.IsNullOrEmpty (myString)

in confronto a

bool empty = myString.IsNullOrEmpty ();

Non vedo cosa abbia a che fare il tuo esempio con l'OOP. Cosa intendi?
Andrew Hare

1
"sembra" che il metodo appartenga all'oggetto
Bluenuance

3
Questo è un cattivo esempio (può lanciare NullReferenceException) ma è sulla strada giusta. Un esempio migliore potrebbe essere la sostituzione di Math.abs (-4) con qualcosa come -4.abs ();
Programmatore fuorilegge

15
per quanto ne so (e per la mia esperienza, se la memoria serve), myString.IsNullOrEmpty () non ha bisogno di lanciare una NullReferenceException perché i metodi di estensione non richiedono un'istanza di oggetto per essere attivati.
David Alpert,

1
Personalmente non sono un fan dei metodi di estensione che sono destinati a funzionare con un'istanza nulla: sembra una cosa al lettore, ma poi fa qualcos'altro.
Mark Simpson

4

Ci sono un sacco di ottime risposte sopra su quali metodi di estensione ti consentono di fare.

La mia risposta breve è: eliminano quasi il bisogno di fabbriche.

Sottolineo solo che non sono un nuovo concetto e una delle più grandi convalide è che sono una caratteristica killer in Objective-C ( categorie ). Aggiungono così tanta flessibilità allo sviluppo basato su framework che NeXT ha avuto come utenti principali i modellatori finanziari NSA e Wall Street.

REALbasic li implementa anche come metodi estesi e sono stati di uso simile semplificando lo sviluppo.


4

Vorrei supportare le altre risposte qui che menzionano una migliore leggibilità del codice come motivo importante alla base dei metodi di estensione. Lo dimostrerò con due aspetti: concatenamento di metodi e chiamate a metodi annidati e ingombro di una query LINQ con nomi di classi statiche privi di significato.


Prendiamo questa query LINQ come esempio:

numbers.Where(x => x > 0).Select(x => -x)

Entrambi Wheree Selectsono metodi di estensione, definiti nella classe statica Enumerable. Pertanto, se i metodi di estensione non esistessero, e questi fossero normali metodi statici, l'ultima riga di codice dovrebbe essenzialmente essere simile a questa:

Enumerable.Select(Enumerable.Where(numbers, x => x > 0), x => -x)

Guarda quanto è diventata peggiore quella query.


Secondo, se ora volessi introdurre il tuo operatore di query, non avresti naturalmente modo di definirlo all'interno della Enumerableclasse statica, come tutti gli altri operatori di query standard, perché Enumerableè nel framework e non hai controllo su quella classe. Pertanto, dovresti definire la tua classe statica contenente metodi di estensione. Potresti quindi ricevere query come questa:

Enumerable.Select(MyEnumerableExtensions.RemoveNegativeNumbers(numbers), x => -x)
//                ^^^^^^^^^^^^^^^^^^^^^^
//                different class name that has zero informational value
//                and, as with 'Enumerable.xxxxxx', only obstructs the
//                query's actual meaning.

3

È vero che puoi aggiungere il tuo metodo (estensione) direttamente nella tua classe. Ma non tutte le classi sono scritte da te. Le classi della libreria principale o di librerie di terze parti sono spesso chiuse e sarebbe impossibile ottenere lo zucchero sintatico senza metodi di estensione. Ma ricorda, i metodi di estensione sono proprio come i metodi autonomi (statici) in es. c ++


3

I metodi di estensione possono anche aiutare a mantenere pulite le classi e le dipendenze delle classi. Ad esempio, potresti aver bisogno di un metodo Bar () per la classe Foo ovunque venga utilizzato Foo. Tuttavia, potresti volere un metodo .ToXml () in un altro assembly e solo per quell'assembly. In tal caso, è possibile aggiungere le dipendenze System.Xml e / o System.Xml.Linq necessarie in quell'assembly e non nell'assembly originale.

Vantaggi: le dipendenze nell'assembly della classe di definizione vengono ridotte alle sole necessità e ad altri assembly che consumano verrà impedito di utilizzare il metodo ToXml (). Vedere questa presentazione PDC per ulteriori riferimenti.


3

Sono d'accordo che i metodi di estensione aumentano la leggibilità del codice, ma in realtà non è nient'altro che metodi di supporto statici.

IMO che utilizza metodi di estensione per aggiungere comportamenti alle tue classi può essere:

Confusione: i programmatori potrebbero credere che i metodi facciano parte del tipo esteso, quindi non capendo perché i metodi sono spariti quando l'estensione-namespace non viene importata.

Un antipattern: decidi di aggiungere comportamenti ai tipi nel tuo framework usando metodi di estensione, quindi spedirli a una persona che entra in unit test. Ora è bloccato con un framework contenente un sacco di metodi che non può falsificare.


Non è vero che uno sviluppatore è bloccato con un sacco di metodi che non può falsificare. Questi metodi di estensione alla fine chiamano un metodo sulla classe / interfaccia che stanno estendendo e questo metodo può essere intercettato dato che è virtuale.
Patrik Hägne

1
Bene, allora dipende da cosa viene fatto nel metodo di estensione. Supponiamo che utilizzi i metodi di estensione forniti su un'interfaccia, senza nemmeno sapere che sono metodi di estensione. Quindi non vuoi simulare una chiamata a un metodo a un'interfaccia, ma ti rendi conto che stai effettivamente invocando un metodo statico. Una chiamata al metodo statico non può essere intercettata da un'API falsa basata su proxy, quindi l'unica opzione è riflettere sul metodo di estensione per scoprire quali metodi falsificare effettivamente. Ancora antipattern se combinato con test unitari IMO.
HaraldV

2

I metodi di estensione sono in realtà l'incorporazione .NET del refactor "Introduce Foreign Method" dal libro di Martin Fowler (fino alla firma del metodo). Vengono con fondamentalmente gli stessi vantaggi e insidie. Nella sezione su questo refactor dice che sono una soluzione per quando non è possibile modificare la classe che dovrebbe realmente possedere il metodo.


2
+1, ma tieni presente che puoi utilizzare metodi di estensione anche con le interfacce.
TrueWill

2

Vedo principalmente i metodi di estensione come un'ammissione che forse non avrebbero dovuto disabilitare le funzioni libere.

Nella comunità C ++, è spesso considerata una buona pratica OOP preferire funzioni libere non membri rispetto ai membri, perché queste funzioni non interrompono l'incapsulamento ottenendo l'accesso ai membri privati ​​di cui non hanno bisogno. I metodi di estensione sembrano essere un modo indiretto per ottenere lo stesso risultato. Cioè, una sintassi più pulita per le funzioni statiche che non hanno accesso ai membri privati.

I metodi di estensione non sono altro che zucchero sintattico, ma non vedo alcun danno nell'usarli.


2
  • Intellisense sull'oggetto stesso invece di dover chiamare qualche brutta funzione di utilità
  • Per le funzioni di conversione, puoi cambiare "XToY (X x)" in "ToY (this X x)", il che si traduce in un grazioso x.ToY () invece di un brutto XToY (x).
  • Estendi le classi su cui non hai controllo
  • Estende la funzionalità delle classi quando non è desiderabile aggiungere metodi alle classi stesse. Ad esempio, è possibile mantenere gli oggetti di business semplici e privi di logica e aggiungere logica di business specifica con brutte dipendenze nei metodi di estensione

2

Li uso per riutilizzare le mie classi di modelli a oggetti. Ho un sacco di classi che rappresentano gli oggetti che ho in un database. Queste classi vengono utilizzate sul lato client solo per visualizzare gli oggetti, quindi l'utilizzo di base è l'accesso alle proprietà.

public class Stock {
   public Code { get; private set; }
   public Name { get; private set; }
}

A causa di questo modello di utilizzo non voglio avere metodi di logica di business in queste classi, quindi creo che ogni logica di business sia un metodo di estensione.

public static class StockExtender {
    public static List <Quote> GetQuotesByDate(this Stock s, DateTime date)
    {...}
}

In questo modo posso utilizzare le stesse classi per l'elaborazione della logica di business e per la visualizzazione dell'interfaccia utente senza sovraccaricare il lato client con codice non necessario.

Una cosa interessante di questa soluzione è che le mie classi del modello a oggetti sono generate dinamicamente utilizzando Mono.Cecil , quindi sarebbe molto difficile aggiungere metodi di logica di business anche se lo volessi. Ho un compilatore che legge i file di definizione XML e genera queste classi stub che rappresentano alcuni oggetti che ho nel database. L'unico approccio in questo caso è estenderli.


1
Potresti usare classi parziali per questo ...
JJoos


1

Nel mio ultimo progetto, ho utilizzato il metodo di estensione per collegare i metodi Validate () agli oggetti business. Ho giustificato questo perché gli oggetti di business in cui vengono trasferiti oggetti serializzabili e verranno utilizzati in domini diversi in quanto sono entità di e-commerce generali come prodotto, cliente, commerciante ecc. logica di convalida con associazione tardiva in un metodo Validate collegato alla classe base dei miei oggetti di trasferimento dati. Spero che questo abbia senso :)


1

Un caso in cui i metodi di estensione erano piuttosto utili è stato in un'applicazione client che utilizza i servizi Web ASMX. A causa della serializzazione, i tipi restituiti dei metodi Web non contengono alcun metodo (sul client sono disponibili solo le proprietà pubbliche di questi tipi).

I metodi di estensione consentivano di aggiungere funzionalità (sul lato client) ai tipi restituiti dai metodi web senza dover creare un altro modello a oggetti o numerose classi wrapper sul lato client.


1

I metodi di estensione possono essere utilizzati per creare una sorta di mixin in C #.

Questo, a sua volta, fornisce una migliore separazione delle preoccupazioni per i concetti ortogonali. Dai un'occhiata a questa risposta come esempio.

Può essere utilizzato anche per abilitare i ruoli in C #, un concetto centrale nell'architettura DCI .


1

Ricorda anche che i metodi di estensione sono stati aggiunti come un modo per aiutare le query di Linq ad essere più leggibili, se usate nel loro stile C #.

Queste 2 affettazione sono assolutamente equivalenti, ma la prima è molto più leggibile (e il divario di leggibilità aumenterebbe ovviamente con più metodi concatenati).

int n1 = new List<int> {1,2,3}.Where(i => i % 2 != 0).Last();

int n2 = Enumerable.Last(Enumerable.Where(new List<int> {1,2,3}, i => i % 2 != 0));

Tieni presente che la sintassi completa dovrebbe anche essere:

int n1 = new List<int> {1,2,3}.Where<int>(i => i % 2 != 0).Last<int>();

int n2 = Enumerable.Last<int>(Enumerable.Where<int>(new List<int> {1,2,3}, i => i % 2 != 0));

Casualmente i parametri di tipo di Wheree Lastnon necessitano di essere esplicitamente menzionati in quanto possono essere desunti grazie alla presenza del primo parametro di questi due metodi (il parametro che viene introdotto dalla parola chiavethis e li rende metodi di estensione).

Questo punto è ovviamente un vantaggio (tra gli altri) dei metodi di estensione e puoi trarne vantaggio in ogni scenario simile in cui è coinvolto il concatenamento di metodi.

In particolare, è il modo più elegante e convincente che ho trovato di avere un metodo di classe base invocabile da qualsiasi sottoclasse e che restituisce un riferimento fortemente tipizzato a questa sottoclasse (con il tipo di sottoclasse).

Esempio (ok, questo scenario è totalmente dozzinale): dopo una buona notte, un animale apre gli occhi e poi lancia un grido; ogni animale apre gli occhi allo stesso modo, mentre un cane abbaia e un'anatra kwaks.

public abstract class Animal
{
    //some code common to all animals
}

public static class AnimalExtension
{
    public static TAnimal OpenTheEyes<TAnimal>(this TAnimal animal) where TAnimal : Animal
    {
        //Some code to flutter one's eyelashes and then open wide
        return animal; //returning a self reference to allow method chaining
    }
}

public class Dog : Animal
{
    public void Bark() { /* ... */ }
}

public class Duck : Animal
{
    public void Kwak() { /* ... */ }
}

class Program
{
    static void Main(string[] args)
    {
        Dog Goofy = new Dog();
        Duck Donald = new Duck();
        Goofy.OpenTheEyes().Bark(); //*1
        Donald.OpenTheEyes().Kwak(); //*2
    }
}

Concettualmente OpenTheEyesdovrebbe essere un Animalmetodo, ma restituirebbe un'istanza della classe astratta Animal, che non conosce metodi di sottoclasse specifici come Barko Ducko altro. Le 2 righe commentate come * 1 e * 2 avrebbero quindi generato un errore di compilazione.

Ma grazie ai metodi di estensione, possiamo avere una specie di "metodo di base che conosce il tipo di sottoclasse su cui è chiamato".

Nota che un semplice metodo generico avrebbe potuto fare il lavoro, ma in un modo molto più scomodo:

public abstract class Animal
{
    //some code common to all animals

    public TAnimal OpenTheEyes<TAnimal>() where TAnimal : Animal
    {
        //Some code to flutter one's eyelashes and then open wide
        return (TAnimal)this; //returning a self reference to allow method chaining
    }
}

Questa volta, nessun parametro e quindi nessuna possibile inferenza sul tipo restituito. La chiamata non può essere altro che:

Goofy.OpenTheEyes<Dog>().Bark();
Donald.OpenTheEyes<Duck>().Kwak();

... che può pesare molto il codice se sono coinvolti più concatenamenti (soprattutto sapendo che il parametro type sarà sempre <Dog>sulla riga di Pippo e <Duck>su quella di Donald ...)


1
La prima volta che ho visto "kwak". È un'ortografia comune in un altro paese? L'unico modo in cui l'ho visto scritto è "ciarlatano".
Brent Rittenhouse

0

Ho solo una parola da dire al riguardo: MANTENIBILITÀ questa è la chiave per l'utilizzo dei metodi di estensione


4
Penso che potresti aver bisogno di più di una parola perché non capisco cosa significhi.
Programmatore fuorilegge

2
In realtà direi che è un argomento contro i metodi di estensione. Uno dei rischi dei metodi di estensione è che possono essere ovunque, creati da tutti. Wildgrow può accadere se non usato con attenzione.
Boris Callens,

Puoi trovare facilmente tutti i riferimenti quando usi EM. Inoltre, per cambiare un metodo a livello globale, puoi farlo da un solo posto
Tamir,

0

Penso che i metodi di estensione aiutino a scrivere codice più chiaro.

Invece di inserire un nuovo metodo nella tua classe, come suggerito dal tuo amico, lo metti nello spazio dei nomi ExtensionMethods. In questo modo mantieni un senso logico dell'ordine nella tua classe. I metodi che non riguardano direttamente la tua classe non la ingombreranno.

Ritengo che i metodi di estensione rendano il tuo codice più chiaro e organizzato in modo più appropriato.


0

Consente al tuo editor / IDE di completare automaticamente i suggerimenti in modo intelligente.


0

Li adoro per la creazione di html. Spesso ci sono sezioni che vengono utilizzate ripetutamente o generate in modo ricorsivo in cui una funzione è utile ma altrimenti interromperebbe il flusso del programma.

        HTML_Out.Append("<ul>");
        foreach (var i in items)
            if (i.Description != "")
            {
                HTML_Out.Append("<li>")
                    .AppendAnchor(new string[]{ urlRoot, i.Description_Norm }, i.Description)
                    .Append("<div>")
                    .AppendImage(iconDir, i.Icon, i.Description)
                    .Append(i.Categories.ToHTML(i.Description_Norm, urlRoot)).Append("</div></li>");
            }

        return HTML_Out.Append("</ul>").ToString();

Ci sono anche situazioni in cui un oggetto necessita di logica personalizzata per essere preparato per i metodi di estensione dell'output HTML che consentono di aggiungere questa funzionalità senza mescolare presentazione e logica all'interno della classe.


0

Ho trovato che i metodi di estensione sono utili per abbinare argomenti generici annidati.

Sembra un po 'strano, ma diciamo di avere una classe generica MyGenericClass<TList>e sappiamo che TList stesso è generico (ad es.List<T> ), non penso che ci sia un modo per estrarre quella "T" annidata dalla lista senza nessuna delle due estensioni metodi o metodi di supporto statici. Se abbiamo solo metodi di supporto statici a nostra disposizione, è (a) brutto e (b) ci costringerà a spostare la funzionalità che appartiene alla classe in una posizione esterna.

ad esempio, per recuperare i tipi in una tupla e convertirli in una firma del metodo possiamo usare metodi di estensione:

public class Tuple { }
public class Tuple<T0> : Tuple { }
public class Tuple<T0, T1> : Tuple<T0> { }

public class Caller<TTuple> where TTuple : Tuple { /* ... */ }

public static class CallerExtensions
{
     public static void Call<T0>(this Caller<Tuple<T0>> caller, T0 p0) { /* ... */ }

     public static void Call<T0, T1>(this Caller<Tuple<T0, T1>> caller, T0 p0, T1 p1) { /* ... */ }
}

new Caller<Tuple<int>>().Call(10);
new Caller<Tuple<string, int>>().Call("Hello", 10);

Detto questo, non sono sicuro di dove dovrebbe essere la linea di divisione: quando un metodo dovrebbe essere un metodo di estensione e quando dovrebbe essere un metodo di supporto statico? qualche idea?


0

Ho zone di input sul mio schermo e tutti devono implementare un comportamento standard qualunque siano i loro tipi esatti (caselle di testo, caselle di controllo, ecc.). Non possono ereditare una classe base comune poiché ogni tipo di zona di input deriva già da una classe specifica (TextInputBox, ecc.)

Forse salendo nella gerarchia dell'ereditarietà potrei trovare un antenato comune come ad esempio WebControl, ma non ho sviluppato la classe framework WebControl e non espone ciò di cui ho bisogno.

Con il metodo di estensione posso:

1) estendi la classe WebControl, quindi ottieni il mio comportamento standard unificato su tutte le mie classi di input

2) in alternativa, fai derivare tutte le mie classi da un'interfaccia, diciamo IInputZone, ed estendi questa interfaccia con metodi. Ora potrò chiamare i metodi delle estensioni relativi all'interfaccia su tutte le mie zone di input. Ho così ottenuto una sorta di ereditarietà multipla poiché le mie zone di input derivavano già da più classi base.


0

Ci sono così tanti ottimi esempi di metodi di estensione ... specialmente su IEnumerables come postato sopra.

ad esempio, se ho un IEnumerable<myObject>posso creare e un metodo di estensione perIEnumerable<myObject>

mylist List<myObject>;

... crea l'elenco

mylist.DisplayInMyWay();

Senza i metodi di estensione dovrebbe chiamare:

myDisplayMethod(myOldArray); // can create more nexted brackets.

un altro ottimo esempio è la creazione di un elenco collegato circolare in un lampo!

Posso prendermene il merito!

elenco collegato circolare utilizzando metodi di estensione

Ora combinali e usando i metodi di estensione il codice si legge come segue.

myNode.NextOrFirst().DisplayInMyWay();

piuttosto che

DisplayInMyWay(NextOrFirst(myNode)).

utilizzo di metodi di estensione È più ordinato e più facile da leggere e più orientato agli oggetti. anche molto vicino a:

myNode.Next.DoSomething()

Mostralo al tuo collega! :)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.