Estoy bastante contento con mi comprensión del modelo de eventos .NET. Creo que podría estar malinterpretando un pequeño matiz del sistema.
Cuando comencé a poner eventos en mis clases, usaría la forma estándar de esta manera:
public event EventHandler<MyEventArgs> MyEvent;
Esto significaba que cualquier cosa que se suscribiera al evento necesitaría un método como:
void HandleThatEvent(object sender, MyEventArgs args){...}
Lo cual es bueno, pero descubrí que rara vez me importaría el remitente, por lo que hizo que se hincharan muchas firmas de métodos.
Entonces cambié a declarar mis propios tipos de delegado
public delegate void MyEventHandler(SomeClass argument);
Lo que redujo el desorden, pero me dejó con un pequeño problema a la hora de escribir controladores:
eventImplmentor.MyEvent += HandleThatEvent;
.
.
.
void HandleThatEvent(/*oh, um, what arguments does it take? Intellisense isn't telling me*/)
Así que tendría que volver a la declaración del delegado y mirar y luego regresar y escribirlos, o compilarlo y esperar a que me lo digan.
Entonces, en cambio, solo estoy usando Action
, Action<T>
o cualquier plantilla que se ajuste.
public event Action<SomeClass> MyEvent;
Para que pueda pasar el cursor sobre el evento y que me digan qué parámetros espera.
Mi pregunta, después de todo eso: ¿hay una mejor práctica para declarar eventos en C #? ¿Debo volver al EventHandler<T>
camino, o es Action<T>
aceptable?
Respuestas:
Para el manejo simple e interno de eventos, existen aquellos que simplemente usan
Action
oAction<T>
, como está proponiendo. Tiendo a usar el patrón estándar, incluido el remitente, incluso para eventos internos, porque nunca se sabe cuándo es posible que luego desee exponer una clase o evento, y no me gustaría la pena de tener que refactorizar el método del evento solo para hacer Es público.Estoy de acuerdo con usted en que la firma de manejo de eventos es un poco más pesada de lo que debería ser para escenarios simples, pero está bien diseñada para manejar la migración incremental ya que los argumentos de eventos adicionales podrían ser necesarios con el tiempo. En general, me quedaría con el patrón estándar, especialmente porque, como notó, solo obtiene el soporte IntelliSense adecuado si lo hace.
Para lo que vale, puse algo de tiempo en esto y se me ocurrió un patrón de manejo de eventos diferente: ¿ Firma del evento en .NET - Usando un 'Remitente' de tipo fuerte? . El objetivo aquí no era eliminar al remitente, sino hacerlo genéricamente tipeado fuerte en
TSender
lugar de tipeado débilmenteSystem.Object
. Funciona muy bien; sin embargo, uno pierde el soporte de IntelliSense cuando hace esto, por lo que hay una desafortunada compensación.En general, me apegaría al patrón estándar, pero es interesante pensar en formas potencialmente mejores de hacerlo.
fuente