tutorial the example event delegate custom and c# events

the - Incremento simple de eventos de C#: uso de "remitente" frente a EventArgs personalizados



raise event c# (6)

Considera este escenario. Tengo un objeto, vamos a llamarlo ... Foo. Foo plantea un evento simple llamado "Cargado". Como parte de la información para el evento, los consumidores necesitarán saber qué objeto Foo planteó el evento. Nuestro equipo ha adoptado el siguiente patrón.

1) Cree una clase nueva que herede de EventArgs; por ejemplo, FooEventArgs: System.EventArgs.

2) Agregue una propiedad de tipo Foo a FooEventArgs, que se configura al pasarla a través del constructor.

3) Declare el evento usando la versión genérica de EventHandler, entonces

public event EventHandler<FooEventArgs> Loaded;

4) Levante el evento de la clase Foo con la siguiente firma:

Loaded(this, new FooEventArgs(this));

Esencialmente, lo que hace esto hace que el "emisor" sea el objeto foo, pero también pone la referencia del objeto foo en el argumento del evento como una propiedad fuertemente tipada.

Una ventaja de hacer esto es que nadie tiene que molestarse en enviar "remitente" cuando manejan el evento, lo que reduce el acoplamiento entre el consumidor del evento y el evento. Otra "ventaja" es que si el tipo del evento eventual tiene que cambiar, y por lo tanto la propiedad fuertemente tipada (que afortunadamente nunca ocurre), entonces en lugar de simplemente tener un código que comience a fallar en el elenco cuando sea nulo, la API realmente se rompe, por lo que puede corregirse en tiempo de compilación.

Para mí, este patrón parece que podría ser excesivo. ¿Deberían confiar más en el parámetro "remitente" y abandonar los argumentos de eventos personalizados? Mi equipo argumenta que nadie realmente usa el parámetro del remitente. ¿Cuál es la mejor práctica para pasar una referencia al objeto de suceso?

EDITAR: Excelentes comentarios hasta el momento, lo dejaré abierto un día más o menos antes de aceptar uno.


El patrón común es usar remitente y no agregar el remitente por separado a EventArgs. El EventArgs personalizado se utiliza para otro estado como un nodo de árbol para un evento de árbol, un booleano (configurable) para un evento cancelable, etc.

Usamos el patrón común ya que también lo usan las clases BCL, y hacer la diferencia para los "eventos hechos por ellos mismos" es potencialmente confuso. Además, tenemos un patrón de suscriptor de editor de IoC global, pero este solo funciona con la firma de delegado de EventHandler normal, ya que los tipos no se conocen de antemano. En este caso, es necesario un cast (por ejemplo, un EventArgs personalizado) de todos modos, así que podríamos enviar el remitente.


En cuanto a las prácticas recomendadas, he visto un nulo suministrado como remitente en Windows Workflow Foundation bastante. Idealmente, sus suscriptores deberían ignorar el objeto que genera eventos.

Por lo tanto, si necesita pasar el objeto llamador como un todo a los controladores, debe colocarlo en un objeto derivado de EventArgs. Alternativamente, prefiero pasar explícitamente las partes del estado del llamador del evento / llamante en lugar de todo el asunto.

Bueno, a veces es más fácil pensar en dotNET 1.1, donde

Control.Invoke()

se usa con la frecuencia

int i;


No creo que esto sea excesivo. Estoy de acuerdo con las ventajas que indica por tener una clase FooEventArgs por separado. Otra ventaja de hacerlo de esa manera es que si necesita agregar más información al evento en el futuro, puede agregar más propiedades a FooEventArgs y no necesita cambiar el delegado.


Supongo que es una cuestión de preferencia hasta cierto punto, pero en mi caso cuando leo los consumers will need to know which foo object raised the event. Inmediatamente pensé que puedes obtener el objeto que provocó el evento desde el argumento del remitente, entonces, ¿cuál es el problema?

Su equipo tiene algunos puntos válidos (al tener una propiedad fuertemente tipada), pero yo diría que trabajar a largo plazo con las pautas marco en lugar de inventar la suya sería una mejor decisión.


Yo diría que eliminas la subclase de EventArgs y usas la propiedad del remitente para identificar al remitente del evento. Creo que el argumento para seguir la convención tiene sus méritos, pero el parámetro en EventArgs no es necesario. Yo personalmente lo soltaría y solo usaría la propiedad del remitente.

Si desea pasarlo como un tipo fuerte, también puede crear un delegado personalizado para usarlo en su evento ...

public delegate void LoadedHandler(FooEventArgs args);

de esa manera podrías tenerlo como un tipo fuerte ... reutilizar delegados es genial, pero si no se ajustan a lo que estás tratando de hacer, no debes sentirte obligado a usar solo los integrados.


Yo diría que la convención tiene mucho que ofrecer. Hay menos para mantener en el largo plazo - esp. si recibes gente nueva