Modo preferito per dichiarare eventi


14

Sono abbastanza contento della mia comprensione del modello di eventi .NET. Penso che potrei fraintendere una piccola sfumatura del sistema.

Quando ho iniziato a inserire eventi nelle mie lezioni, avrei usato il modo standard in questo modo:

public event EventHandler<MyEventArgs> MyEvent;

Ciò significava che qualsiasi abbonamento all'evento avrebbe bisogno di un metodo come:

void HandleThatEvent(object sender, MyEventArgs args){...}

Il che è carino, ma ho scoperto che raramente mi interesserebbe il mittente, quindi ha gonfiato molte firme dei metodi.

Quindi sono passato a dichiarare i miei tipi di delegato

public delegate void MyEventHandler(SomeClass argument);

Che ha ridotto il disordine, ma mi ha lasciato un piccolo problema quando si trattava di scrivere gestori:

eventImplmentor.MyEvent += HandleThatEvent;
.
.
.
void HandleThatEvent(/*oh, um, what arguments does it take? Intellisense isn't telling me*/)

Quindi dovrei tornare alla dichiarazione del delegato e guardare e poi tornare indietro e scriverli, o compilarli e attendere che gli venga detto.

Quindi ora invece sto solo usando Action, Action<T>o qualunque modello si adatti.

public event Action<SomeClass> MyEvent;

In modo che possa passare il mouse sopra l'evento e sapere quali parametri si aspetta.

La mia domanda, dopo tutto: esiste una best practice per dichiarare eventi in C #? Devo tornare sulla EventHandler<T>strada, o è Action<T>accettabile?


Non dimenticare di assicurarti che il gestore sia copiato localmente nel punto in cui viene generato l'evento, per cui è sempre necessario farlo per sicurezza del thread.
Snoop

Puoi scrivere i tuoi eventi intelligenti, meschini e sicuri di tipo nel codice incapsulato, ma tutto ciò che pubblichi dovrebbe seguire il modello standard o confonderà semplicemente gli utenti della tua classe (e apparentemente anche alcuni strumenti).
Martin Maat,

Risposte:


8

Per una semplice gestione interna degli eventi, ci sono quelli che usano semplicemente Actiono Action<T>, come stai proponendo. Tendo a usare il modello standard, incluso il Mittente, anche per eventi interni, perché non sai mai quando potresti voler esporre successivamente una classe o un evento, e non vorrei la pena di dover refactificare il metodo dell'evento solo per fare è pubblico.

Sono d'accordo con te sul fatto che la firma di gestione degli eventi sia un po 'più pesante di quanto dovrebbe essere per scenari semplici, ma è ben progettata per gestire la migrazione incrementale poiché nel tempo potrebbero rendersi necessari ulteriori argomenti sugli eventi. Nel complesso, mi atterrei al modello standard, soprattutto perché, come hai notato, riceverai il supporto IntelliSense adeguato solo se lo fai.

Per quello che vale, ho dedicato un po 'di tempo a questo e ho trovato un diverso modello di gestione degli eventi : Firma degli eventi in .NET - Usando un "mittente" con caratteri forti? . L'obiettivo qui non era quello di rimuovere il mittente, ma di renderlo tipicamente forte come TSenderinvece che debolmente digitato come System.Object. Funziona molto bene; tuttavia, si perde il supporto di IntelliSense quando si esegue questa operazione, quindi si verifica uno sfortunato compromesso.

Nel complesso, mi atterrei al modello standard, ma è interessante pensare a modi potenzialmente migliori per farlo.


Grazie per avermi indicato la tua domanda SO. È molto interessante. Continuo a non capire perché sia ​​così importante che il mittente sia obbligatorio. Il più delle volte non mi interessa il mittente. È solo una regola arbitraria per la SM?
Matt Ellen,

No, ovviamente puoi dichiarare i tuoi delegati come preferisci. È politica .NET includere sempre il mittente e non è affatto una cattiva idea.
Neil,

@Neil: capisco che a volte è utile, ma non capisco la politica di farlo sempre, specialmente perché MS consiglia di fare eventi a modo loro. Una delle cose che mi piacciono molto degli eventi è la capacità di separare le lezioni. Se includo l'oggetto, viene nuovamente accoppiato nuovamente. Se è solo una questione di conformità CLS, allora posso conviverci.
Matt Ellen,

Viene nuovamente accoppiato di nuovo solo se si utilizza l'oggetto mittente, altrimenti non importa quale valore viene inserito come valore del mittente poiché non lo si utilizza. La dipendenza esiste solo se è necessario che ci sia una dipendenza. Vedo da dove vieni, e se il mittente di oggetto scomparisse da tutto il codice di qualsiasi server del pianeta, non starei sveglio la notte.
Neil,

Sì, puoi inviare "null" come mittente se vuoi davvero ... Ma, includendo il mittente, lo stesso gestore di eventi potrebbe annullare l'iscrizione se lo desiderasse. Nel complesso, però, direi che conoscere la fonte dell'evento è di solito piuttosto importante.
Mike Rosenblum,
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.