it-swarm.it

Uso nel mondo reale dei delegati C #

Penso di comprendere concettualmente i delegati di C #, tuttavia, faccio fatica a trovare un esempio nel 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.

16
AlexC

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.

Linq usa il Func<T> e Action<T> delega dappertutto come parametri.

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

12
Oded

Praticamente qualsiasi cosa usando Observer Pattern probabilmente implementerebbe i delegati.

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

12
whatsisname

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
James Love

I delegati sono particolarmente utili come soluzione per 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.

9
Scott Whitlock

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, la funzione qsort 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 tutte prendono come riferimento gli indicatori di funzione.

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 in OOP lingue, tranne quando si passa l'indirizzo di una funzione è necessario passare anche l'indirizzo dell'oggetto di cui la funzione è un metodo. Ecco due cose che devi passare Quindi un delegato è proprio questo, e permette ancora di usare quel buon vecchio schema.

5
Mike Dunlavey

Ecco un semplice esempio che mostra quanto possano essere utili i delegati nella creazione di un semplice codice che segue il principio DRY. Permette anche 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);    
        }
    }
}
3
ChaosPandion

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.

2
Ken

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
Steven Evers

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, usando Action<...> o Func<...> è molto più elegante della creazione di un'interfaccia a un metodo dedicata.

1
nikie