Domanda

  • Quando ha senso usare i metodi di estensione?
  • L'aggiunta di metodi di estensione a un tipo influisce sulle prestazioni?

    Queste domande fanno seguito alla domanda che ho posto in precedenza su Metodi di estensione .

        
  • È stato utile?

    Soluzione

    Quando ha senso usare i metodi di estensione?

    Hanno senso quando si utilizza LINQ e si desidera incatenare o reindirizzare l'output funzionale da una funzione all'altra. Migliora la leggibilità del codice e consente di esprimere un concetto in modo più elegante (qualunque cosa valga la pena).

    Consentono anche di dare l'apparenza di metodi di istanza su qualsiasi tipo che ti piace senza modificare l'origine di quel tipo, questo può spesso aiutare la leggibilità e l'espressività del tuo codice quando viene usato ragionevolmente

    L'aggiunta di metodi di estensione a un tipo influisce sulle prestazioni?

    Nota che un metodo di estensione chiama come:

    instance.SomeExtensionMethod()
    

    viene compilato in:

    StaticExtensionMethodClass.SomeExtensionMethod(instance);
    

    quindi le prestazioni saranno le stesse di qualsiasi altra chiamata di metodo statico.

    Altri suggerimenti

    Dalla mia risposta qui :

    Per quanto riguarda un uso pratico dei metodi di estensione, è possibile aggiungere nuovi metodi a una classe senza derivarne una nuova.

    Dai un'occhiata al seguente esempio:

    public class extended {
        public int sum() {
            return 7+3+2;
        }
    }
    
    public static class extending {
        public static float average(this extended extnd) {
            return extnd.sum() / 3;
        }
    }
    

    Come vedi, la classe Extending sta aggiungendo un metodo chiamato media alla classe Extended. Per ottenere la media, si chiama il metodo average, poiché appartiene alla extended classe:

    extended ex = new extended();
    
    Console.WriteLine(ex.average());
    

    Riferimento: http://aspguy.wordpress.com/2008/07/03/a-practical-use-of-serialization-and-extension-methods-in-c-30/


    Per quanto riguarda Prestazioni , penso che puoi vedere un miglioramento con i metodi di estensione poiché non vengono mai inviati in modo dinamico, ma tutto dipende da come viene implementato il metodo dinamico.

    Viene utilizzato per estendere (aggiungere) la funzionalità delle classi esistenti senza modificarle.

    Puoi vederlo nel modo in cui LINQ (spazio dei nomi System.Linq e altri) aggiunge molte funzionalità a tutte le raccolte.

    Un altro uso interessante dei metodi di estensione è quando si desidera aggiungere determinate funzionalità a una classe in uno spazio dei nomi ma non in un altro. Un esempio specifico è l'aggiunta di metodi per facilitare i test unitari: non vorrai che ingombrassero i tuoi assiemi di produzione, ma sono fantastici quando si scrivono test unitari.

    Oltre alle altre risposte, i metodi di estensione sono un ottimo modo per aggiungere l'implementazione della piastra caldaia alle interfacce. Ad esempio, se si desidera che tutti gli elenchi siano ordinabili, aggiungere un metodo di estensione per IList<T>.

    Puoi (come già detto) usare anche metodi di estensione per aggiungere metodi a classi al di fuori del tuo controllo; hai mai desiderato un metodo Reverse() su string? Aggiungi uno!

    L'unica differenza è che i metodi di estensione non usano il virtuale e non esiste un controllo null. Puoi usarlo a tuo vantaggio se ti piace:

    public static void ThrowIfNull<T>(this T obj, string name) where T : class
    {
        if(obj == null) throw new ArgumentNullException(name);
    }
    

    A differenza dei normali metodi di utilità, rendono molto semplice la scrittura di interfacce fluide; questo è uno dei motivi della loro esistenza, ovvero con LINQ:

    var foo = source.Where(predicate).OrderBy(selector);
    

    è molto più leggibile di:

    var foo = Enumerable.OrderBy(Enumerable.Where(source,predicate),selector);
    

    Con i metodi regolari, per utilizzare il primo approccio dovrebbero essere metodi di istanza regolari, che richiederebbero modifiche (ad esempio) a IEnumerable<T> - non desiderabili.

    I metodi di estensione brillano ovunque venga utilizzata la programmazione funzionale.

    Considera quasi tutte le funzioni a livello di modulo che hai già nella tua app e cosa diventano quando le tagghi come metodi di estensione. Diventano un'opportunità per & Quot; voce attiva & Quot; oltre " voce passiva " ;. Voce attiva significa che il codice legge come se un'istanza fornisca il proprio metodo per eseguire una determinata attività, piuttosto che far sì che la funzione esegua un'azione passivamente su di essa.

    ExtendUnlimitedCredit(AddVIP(tblCustomer, "Bill Gates"))
    

    vs.

    tblCustomer.AddVIP("Bill Gates").ExtendUnlimitedCredit()
    

    I metodi di estensione rendono semplice questa trasformazione. Eliminare le chiamate di funzione nidificate con & Quot; voce attiva & Quot; il codice è spesso un miglioramento. Inoltre, poiché il nostro negozio blocca le sue classi principali, siamo stati in grado di utilizzare solo le chiamate di funzioni nidificate prima dei metodi di estensione.

    Le altre grandi cose sui metodi di estensione:

    1. Rendono più visibili le tue funzioni (grazie a Intellisense). E se hai fornito markup in linea descrivendo lo scopo e l'uso della tua funzione, Intellisense fornirà anche una descrizione utile del descrittore del metodo e del suo utilizzo allo sviluppatore che lo scopre (semplicemente premendo il punto). Le funzioni non contrassegnate come metodi di estensione non vengono scoperte così facilmente, potrebbero non essere utilizzate e, di conseguenza, qualcun altro potrebbe inventare il proprio sapore di detta funzione.

    2. Mentre in realtà non è possibile implementare un metodo per un'interfaccia, un metodo di estensione offre un mezzo alternativo che dà l'apparenza che & # 8217; l'hai fatto.

    Non sono a conoscenza di implicazioni sulle prestazioni. L'uso dei metodi di estensione ha molto senso quando non si ha accesso al codice sorgente e quindi non è possibile aggiungere direttamente il metodo alla classe e il metodo ha senso da implementare come funzione. Questo va al commento che ho fatto sulla tua domanda precedente, in cui un'altra persona ha fornito un campione per un metodo di estensione sulla classe 'string' che ha restituito un bool in base al fatto che la stringa fosse o-mail valida. Questo, IMO, è un esempio di quando NON usare un metodo di estensione, perché quella funzione non è fondamentale per il tipo di stringa. L'aggiunta di una funzione Left (int) e una Right (int) a 'string' ha comunque senso.

    Li uso per riutilizzare le mie classi di modelli di oggetti. Ho un gruppo di classi che rappresentano oggetti che ho in un database. Queste classi vengono utilizzate nel lato client solo per visualizzare gli oggetti in modo che l'utilizzo di base acceda alle proprietà.

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

    A causa di quel modello di utilizzo non voglio avere metodi di business logic in queste classi, quindi faccio in modo 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 usare le stesse classi per l'elaborazione della logica aziendale 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 di modelli di oggetti sono generate dinamicamente usando Mono.Cecil , quindi sarebbe molto difficile aggiungere metodi di business logic anche se lo volessi. Ho un compilatore che legge i file di definizione XML e genera queste classi di stub che rappresentano alcuni oggetti che ho nel database. L'unico approccio in questo caso è quello di estenderli.

    Affrontare la tua seconda domanda: la mia regola pratica è che il metodo di estensione dovrebbe essere un " naturale estensione della funzionalità " sul tipo o che dovrebbe essere una parte mantenibile e leggibile di un'interfaccia fluida.

    Un esempio di quot &; estensione naturale della funzionalità " sta estendendo un lettore di dati per restituire un valore predefinito se viene rilevato un DBNull. Non così naturale sarebbe l'estensione del lettore di dati per restituire un'istanza dell'entità rappresentata dai dati in più campi. In quest'ultimo caso, stai iniettando le responsabilità sbagliate nell'oggetto povero :).

    Autorizzato sotto: CC-BY-SA insieme a attribuzione
    Non affiliato a StackOverflow
    scroll top