Uso nel mondo reale dei delegati C # [chiuso]


16

Penso di comprendere concettualmente i delegati di C #, tuttavia, faccio fatica a trovare un esempio del mondo reale in cui sarebbero utili. Puoi fornire alcune risposte che spieghino in dettaglio come sono stati usati i delegati C # in applicazioni reali e quali problemi ti hanno permesso di aggirare.


2
Quasi ogni singola classe nel framework .NET espone una serie di eventi, quindi il gioco è fatto. È solo un modo per incapsulare alcune unità di lavoro. Ad esempio, supponiamo che tu stia implementando una struttura ad albero binario generica in C. Beh, l'unico modo per ordinare il tuo albero sarebbe quello di prendere come parametro un puntatore a funzione che sappia come fare l'ordinamento.
Ed S.

Risposte:


16

Il codice della GUI utilizza delegati per gestire eventi, come clic sui pulsanti, spostamenti di finestre. L'uso del delegato consente di avere una funzione chiamata ogni volta che si verifica l'evento. Un esempio potrebbe essere il collegamento di una funzione che salva i dati in un pulsante "Salva" sull'interfaccia. Quando si fa clic sul pulsante, viene impostato per eseguire la funzione che salva i dati. È utile nella programmazione della GUI perché l'intero programma potrebbe essere in attesa che l'utente faccia qualcosa e tu non hai modo di sapere cosa faranno prima. L'uso dei delegati consente di collegare la funzionalità del programma all'interfaccia utente in modo tale che l'utente possa fare le cose nel modo che desidera.


2
++ Hai ragione, ma lo odio ancora :-), così secoli fa mi sono inventato questo .
Mike Dunlavey,

12

Linq utilizza i delegati Func<T>e in Action<T>tutto il luogo come parametri.

Consentono di utilizzare le espressioni lambda come parametri e definiscono l'azione da eseguire come parte dell'elenco dei parametri.


12

Praticamente qualsiasi cosa usando il modello Observer implementerebbe probabilmente i delegati.

Leggi la descrizione e probabilmente immaginerai alcuni scenari in cui li useresti. La gestione degli eventi della GUI è un esempio comune.


+1, Il modello di strategia è davvero il punto in cui brillano i delegati, cioè hai una classe in cui un metodo fa qualcosa, ma vuoi che qualcosa sia intercambiabile e senza dipendenza diretta, ergo delegates. Si noti che gli eventi soddisfano in qualche modo le stesse esigenze dei delegati, la differenza è che si utilizzano i delegati quando è necessario reagire su un valore di ritorno, mentre si attivano solo eventi e qualunque sarà.
Homde,

9

I delegati sono estremamente utili nella programmazione asincrona.

Hai una classe che fa cose in modo asincrono e ha un callback. Puoi richiamare il metodo delegato al momento della richiamata e l'implementazione della classe eseguirà la logica descritta nel metodo delegato.


9

I delegati sono particolarmente utili come soluzione per il buco nel modello centrale . In sostanza, ci sono molti casi in cui si desidera racchiudere un set unico di istruzioni all'interno di un gruppo comune di istruzioni. È particolarmente difficile se le istruzioni prima e dopo il bit univoco devono condividere lo stato. Con i delegati, puoi semplicemente passare un delegato in una funzione. La funzione esegue il bit precedente, esegue il delegato, quindi esegue il bit successivo.


5

Ai vecchi tempi di linguaggi non OOP come Fortran e C, era incredibilmente utile poter ricevere un argomento da una subroutine che era un puntatore a una funzione. Ad esempio, ilqsort funzione funziona con una funzione di confronto fornita dall'utente. Esistono numerose subroutine per la risoluzione di equazioni differenziali ordinarie o per l'ottimizzazione di funzioni e prendono tutti i puntatori di funzione come argomenti.

Nei sistemi a finestre, tutti i tipi di callback seguono lo stesso schema.

In Lisp, anche ai primi tempi, c'era qualcosa chiamato "argomento funzionale" o FUNARG, che non era solo una funzione, ma conteneva anche un contesto di archiviazione in cui poteva ricordare e interagire con parte del mondo esterno.

Questa stessa esigenza esiste nei linguaggi OOP, tranne quando si passa l'indirizzo di una funzione è necessario passare anche l'indirizzo dell'oggetto di cui la funzione è un metodo. Sono due cose che devi passare. Quindi un delegato è proprio questo e consente di utilizzare ancora quel buon vecchio schema.


3

Ecco un semplice esempio che mostra quanto possano essere utili i delegati nella creazione di un codice semplice che segue il principio DRY. Inoltre, consente di mantenere il codice estremamente vicino a dove è necessario.

Action<Button, Action<Button>> prepareButton = 
    (btn, nxt) => { 
        btn.Height = 32;
        btn.Width= 64;
        nxt(btn);
    };

prepareButton(myBtn1, btn => btn.Text = "A");
prepareButton(myBtn2, btn => btn.Text = "B");
prepareButton(myBtn3, btn => btn.Text = "C");

Ecco un esempio reale del vantaggio offerto dai delegati.

protected override void PageInitialize()
{
    const string selectCodeFormat = "javascript:selectCode('{0}', '{1}');";
    const string onClick = "return toggleElement(this);";

    Func<HtmlGenericControl> getElement = null;
    Action<HtmlGenericControl> setElement = null, addChild = null;
    HtmlGenericControl level1Element = null, level2Element = null, level3Element = null, level4Element = null;
    string className = null, code = null, description = null;           

    using (var records = Core.Database.ExecuteRecords("code.SocCodeTree"))
    {
        while (records.Read())
        {
            code = records.GetString("Code");
            description = records.GetString("Description"); 

            if (records.GetString("Level4") != "")
            {
                className = "Level4";
                setElement = e => level4Element = e;
                getElement = () => level4Element;
                addChild = e => level3Element.Controls.Add(e);
            }
            else if (records.GetString("Level3") != "")
            {
                className = "Level3";
                setElement = e => level3Element = e;
                getElement = () => level3Element;
                addChild = e => level2Element.Controls.Add(e);
            }
            else if (records.GetString("Level2") != "")
            {
                className = "Level2";
                setElement = e => level2Element = e;
                getElement = () => level2Element;
                addChild = e => level1Element.Controls.Add(e);
            }
            else
            {
                className = "Level1";
                setElement = e => level1Element = e;
                getElement = () => level1Element;
                addChild = e => Root.Controls.Add(e);
            }

            var child = new HtmlGenericControl("li");
            child.Attributes["class"] = className;
            var span = new HtmlGenericControl("span") { 
                InnerText = code + " - " + description + " - " 
            };
            span.Attributes["onclick"] = onClick;
            child.Controls.Add(span);
            var a = new HtmlAnchor() { 
                InnerText = "Select", 
                HRef = string.Format(selectCodeFormat, code, description) 
            };
            child.Controls.Add(a);
            setElement(new HtmlGenericControl("ul"));
            child.Controls.Add(getElement());
            addChild(child);    
        }
    }
}

2

Il mio primo incontro con i delegati è stato la ricerca di un aggiornamento del programma (Windows Form C # 3.5) scaricando un file dal mio sito Web, ma per evitare che l'aggiornamento controllasse il blocco dell'intero programma ho usato un delegato e un thread per farlo in modo asincrono.


1

Ho visto interessanti implementazioni del modello di strategia che utilizza i delegati in modo efficace. (ovvero la strategia è un delegato)

Quello che stavo guardando era per l'individuazione dei percorsi in cui l'algoritmo per trovare il percorso era un delegato che poteva essere (ri) assegnato in fase di esecuzione in modo da poter utilizzare algoritmi diversi (BFS vs A * ecc.)


1

Molti dei modelli GoF classici possono essere implementati con i delegati: ad esempio, modello Comando, modello Visitatore, modello Strategia, modello Factory e modello Observer possono spesso essere implementati con un semplice delegato. A volte, una classe è migliore (ad esempio quando un comando ha bisogno di un nome o un oggetto strategia deve essere serializzato) ma nella maggior parte dei casi, l'utilizzo Action<...>o Func<...>è molto più elegante della creazione di un'interfaccia a un metodo dedicata.

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.