Condividi tramite


Differenziare delegati ed eventi

Precedente

Gli sviluppatori che non hanno esperienza con la piattaforma .NET spesso hanno difficoltà quando si decide tra una progettazione basata su delegates e una progettazione basata su events. La scelta di delegati o eventi è spesso difficile, perché le due funzionalità del linguaggio sono simili. Gli eventi vengono creati anche usando il supporto della lingua per i delegati. Una dichiarazione del gestore eventi dichiara un tipo delegato.

Entrambi offrono uno scenario di associazione tardiva: consentono scenari in cui un componente comunica chiamando un metodo noto solo in fase di esecuzione. Supportano entrambi i metodi di sottoscrizione singoli e multipli. È possibile trovare questi termini denominati supporto per cast singolo e multicast. Entrambi supportano una sintassi simile per l'aggiunta e la rimozione di gestori. Infine, generare un evento e chiamare un delegato usa esattamente la stessa sintassi di chiamata del metodo. Entrambi supportano la stessa sintassi del metodo Invoke() da usare con l'operatore ?..

Con tutte queste somiglianze, è facile avere difficoltà a determinare quando usare quale.

L'ascolto degli eventi è facoltativo

La considerazione più importante per determinare quale funzionalità del linguaggio usare è se deve essere presente o meno un sottoscrittore collegato. Se il codice deve chiamare il codice fornito dal sottoscrittore, è necessario usare una progettazione basata su delegati quando è necessario implementare il callback. Se il codice può completare tutte le operazioni senza chiamare alcun sottoscrittore, è consigliabile usare una progettazione basata su eventi.

Si considerino gli esempi compilati durante questa sezione. Il codice creato usando List.Sort() deve essere assegnato a una funzione di confronto per ordinare correttamente gli elementi. Le query LINQ devono essere accompagnate da delegati per determinare quali elementi devono essere restituiti. Entrambi hanno usato una progettazione compilata con delegati.

Si consideri l'evento Progress. Segnala lo stato di avanzamento di un'attività. L'attività continua a procedere indipendentemente dal fatto che siano presenti listener. Il FileSearcher è un altro esempio. Continuerebbe a cercare e trovare tutti i file richiesti, anche senza sottoscrittori degli eventi associati. I controlli dell'esperienza utente continuano a funzionare correttamente, anche quando non sono presenti sottoscrittori in ascolto degli eventi. Entrambi usano progettazioni basate su eventi.

I valori restituiti richiedono delegati

Un'altra considerazione è il prototipo del metodo che si vuole usare per il metodo delegato. Come si è visto, i delegati usati per gli eventi hanno tutti un tipo restituito void. Esistono idiomi per creare gestori eventi che restituiscono informazioni alle origini eventi tramite la modifica delle proprietà dell'oggetto argomento evento. Anche se questi idiomi funzionano, non sono altrettanto naturali come la restituzione di un valore da un metodo.

Si noti che questi due euristici possono spesso essere presenti entrambi: se il metodo delegato restituisce un valore, influisce in qualche modo sull'algoritmo.

Gli eventi hanno un'invocazione privata

Le classi diverse da quelle in cui è contenuto un evento possono aggiungere e rimuovere solo listener di eventi; solo la classe contenente l'evento può richiamare l'evento. Gli eventi sono in genere membri della classe pubblica. In confronto, i delegati vengono spesso passati come parametri e archiviati come membri privati della classe, se vengono archiviati.

I listener di eventi hanno spesso durate più lunghe

La durata più lunga dei listener di eventi è una giustificazione leggermente più debole. Tuttavia, è possibile che i design basati su eventi siano più naturali quando l'origine degli eventi genera eventi su un lungo periodo di tempo. È possibile visualizzare esempi di progettazione basata su eventi per i controlli UX in molti sistemi. Dopo esserti iscritto a un evento, la sorgente dell'evento può generare eventi per tutta la durata del programma. È possibile annullare la sottoscrizione dagli eventi quando non sono più necessari.

A differenza di molte progettazioni basate su delegati, in cui un delegato viene usato come argomento per un metodo e il delegato non viene usato dopo la restituzione di tale metodo.

Valutare attentamente

Le considerazioni precedenti non sono regole rigide e inflessibili. Rappresentano invece linee guida che consentono di decidere quale scelta è migliore per l'utilizzo specifico. Poiché sono simili, è anche possibile creare un prototipo di entrambi e considerare che sarebbe più naturale lavorare con. Entrambi gestiscono correttamente scenari di associazione tardiva. Usa quello che comunica il tuo design al meglio.