Il mittente di un evento dovrebbe essere sempre un oggetto generico?


10

Quando si programmano eventi in C #, si consiglia di creare un delegato sotto forma di:

delegate XEventHandler(object sender, XEventArgs e);

La mia domanda è sul primo argomento del delegato, object sender. Deve essere sempre un generico object? Avere un mittente di tipo objectcomporta sempre un codice simile a questo.

val = ((ConcreteType)sender).Property;

o, ancora più dettagliato,

ConcreteType obj = sender as ConcreteType
if (obj != null) { ... }

Un argomento contro mittenti fortemente tipizzati è che altri oggetti possono inoltrare l'evento senza preoccuparsi del tipo. Sebbene ciò possa avere senso negli ambienti con GUI, non sono sicuro che possa trarne beneficio al di fuori di una GUI.

Cosa succede se la classe del mittente è sempre conosciuta (almeno come una classe astratta)? Ad esempio, se sto implementando un ListChangedevento in una Listclasse astratta e se altre classi lo erediteranno (ad esempio LinkedList, ArrayList), va bene definire il mio delegato con un mittente di tipo List?

delegate ListChangedEventHander(List sender, ListChangedEventArgs e);

Oppure, ci sarebbe un aspetto negativo nel cambiare il convenzionale object senderin un tipo più specifico?

Risposte:


10

A questo punto, è principalmente una convenzione (piuttosto forte). Cioè, sarà strano se scrivi una libreria che non segue quella convenzione.

Le linee guida per la progettazione di eventi dicono:

DO uso objectcome il tipo del primo parametro del gestore eventi, e chiamarlo sender.

Tuttavia, è possibile notare che la guida attuale afferma che non è necessario definire il proprio delegato personalizzato per gli eventi, ma utilizzare EventHandler<T>invece, se possibile.

Per quanto riguarda il design, immagino che promuova anche il riutilizzo dei gestori di eventi, anche in contesti non originariamente previsti dal progettista originale dell'evento.


2
Ughhh ... solo perché Microsoft ha deciso di rendere le proprie linee guida abbastanza generiche da essere applicabili a tutti, non significa che sia una buona idea per tutti gli altri seguire le loro linee guida. È molto probabile che "tutti gli altri" non stiano scrivendo il codice per essere utilizzato da milioni di altri sviluppatori. Mi sono sentito a circa 2/3 delle raccomandazioni dal link che hai fornito.
Dunk,

A dire il vero, questa "linea guida" sembra più o meno la notazione ungherese dell'API di Windows. Qualcuno brillante lo ha iniziato per una ragione davvero buona e poi tutti hanno iniziato ad abusarne. Quando c'è una linea guida, è meglio che ci sia una buona ragione dietro quella linea guida. E quello che penso sia la ragione di questa linea guida è che lo System.Windows.Formsspazio dei nomi è il luogo in cui gli eventi sono maggiormente utilizzati e che ha senso iscriversi Clickall'evento di Buttono a CheckBox. Pertanto, il mittente deve essere generico. ...
sampathsris,

... Ma quando si tratta di altre aree di funzionalità, più specifiche e contenute, potrebbe non essere necessario che il mittente sia una classe generica. Vedi di nuovo il mio esempio di una gerarchia di classi di Lists.
sampathsris,

11
@Dunk: ed è questo il punto. Questa linea guida proviene dalle Linee guida per la progettazione del framework, che riguardano principalmente il codice utilizzato da altri . Non perché è la soluzione migliore, ma perché è la meno sorprendente. Questa è l'opzione migliore per un framework . Per le librerie più piccole, se il caso d'uso è ben specificato, è applicabile meno della guida. Microsoft lo dice esplicitamente all'inizio del libro.
Magus,

1
Non sto discutendo con la risposta, l'ho persino votata perché proviene da una fonte attendibile. Sto solo dicendo che non avrei usato le linee guida. Se un evento dovrebbe inviare dati specifici, invierò semplicemente i dati specifici. Inoltre, la funzione dell'evento funziona perfettamente se li usi come erano destinati a essere utilizzati.
Dunk,

0

Il motivo della raccomandazione è che consente future modifiche che non richiedono necessariamente modifiche al codice esistente, e in particolare all'interfaccia pubblica.

Lo stesso meccanismo di eventi può ancora essere utilizzato per eventi in stile "VB6", ma dovrai cambiare tutti i consumatori esistenti se dovessi mai cambiare la firma (o peggio: creare nuove versioni degli stessi eventi). Con l'approccio consigliato, purché gli elementi più recenti ereditino da quelli esistenti, è possibile aggiornare la firma senza correggere il codice esistente.

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.