2010-06-29 15 views
5

que entienden los beneficios de eventos utilizando los tipos de delegado con la firma delegate void delegate_name(object sender, EventArgs e)Beneficios de eventos utilizando EventArgs/EventArgs <T> tipos de delegado en lugar de ...

a) Pero además del hecho de que nos puede ahorrar algo de mecanografía, ¿hay alguna otra ¿Por qué deberíamos usar los tipos de delegado ya definidos EventHandler/EventHandler<T> en lugar de declarar nuestros propios tipos de delegados con la firma delegate void delegate_name(object sender, EventArgs e)?

b) Dos otra razón que se me ocurre para el uso de los tipos predefinidos de delegado EventArgs/EventArgs<T> son:

  • personas que consumen evento en particular (por ejemplo event EventHandler my_event) sabrá de inmediato cómo utilizar ese evento?

  • quizá algunos métodos populares de terceros aceptan como parámetros EventHandler/ EventHandler<T> tipos de delegado, y por lo tanto, si hay alguna posibilidad de que nuestro código puede utilizar los mismos métodos de terceros, debemos utilizar delegados predefinidos EventHandler/Eventhandler<T>?

agradecimiento

Respuesta

11

Para mí, la pregunta es un poco extraño. ¿Cuál sería el beneficio de hacer esto de otra manera (definiendo tipos de delegados que coincidan exactamente con EventHandler<TEventArgs> para algunos TEventArgs)?

Dicho esto, hay al menos un beneficio que se me ocurre hacerlo de la manera "normal": ciertas API ya esperan tratar con delegados EventHandler<TEventArgs>; por ejemplo, Rx Extensions incluye un método que tiene este aspecto:

Observable.FromEvent<TEventArgs>(
    Action<EventHandler<TEventArgs>> addHandler, 
    Action<EventHandler<TEventArgs>> removeHandler 
); 

Si ha definido su propio delegado, utilizando métodos como éste - la cual esperan EventHandler<TEventArgs> delegados - se hace más compleja de lo necesario para ningún beneficio adicional (que Puedo ver, de todos modos).

+0

gracias a todos por su ayuda – flockofcode

5

que haya respondido a su propia pregunta:

  • sintáctico azúcar (menos de escribir) para mantener la convención
  • Interoperabilidad (utilizando el EventHandler tipo de integrar fácilmente los eventos de otras bibliotecas
let

En resumen, no hay una buena razón para no usarlo a menos que se vea obligado (lo que generalmente es el resultado de personas que no lo conocen o no lo entienden).

7

Se le olvidó importante:

  • el loco que mantendrá su código algún día descubrir dónde vive y hacer daño.
+0

+1 ¡Esta es una preocupación legítima, creo! – ewall

2

De Pro C# 2008 and the .NET 3.5 Platform:

Cuando el compilador procesa el evento palabra clave, se le proporciona automáticamente con los métodos de registro y desregistro *, así como cualquier miembro de las variables necesarias ** para sus tipos de delegado . ... Sin duda, la palabra clave del evento es poco más que azúcar sintáctica, ya que simplemente le ahorra tiempo de tipeo.

* Esto incluye la sobrecarga de los prácticos operadores += y -=.

** ... que ya están marcados private para que no puedan ejecutarse.

Cuando utiliza el delegado genérico EventHandler, ni siquiera tiene que escribir su tipo de delegado personalizado en absoluto.

2

Voy a mover el barco aquí y propondré algo completamente herético. Solía ​​estar firmemente en el campo EventArgs porque me aferré a la mentalidad de "MS recomienda esto y siempre se ha hecho así", pero con el tiempo llegué a odiar EventArgs. ¿Por qué?

  • promueve un estilo de NET-1.0ish de codificación que se basa en la tipificación débil la conversión de tipos/y me hace sentir sucia.
  • Obliga a su clase que implementa el evento a contaminar el montón con nuevas instancias EventArg cada vez que se dispara, lo que también me inquieta. ¿Por qué no hacer que mis eventos les den a los suscriptores exactamente lo que necesitan en lugar de completarlo en una clase extra que no hace nada por mí?
  • Las firmas de sus métodos de devolución de llamada que se suscriben al evento se ven como basura y tienen muy pocos detalles semánticos, por ej. object sender - ¿QUÉ es remitente?!?!

Lo que hago ahora es declarar mis propios delegados de controladores de eventos, que guardo cuidadosamente en su propia carpeta de "delegados" en mi solución, así como su propio espacio de nombres. Así que mi delegado puede residir en su propio archivo de la siguiente manera:

namespace MyAPI.Data.Delegates 
{ 
    public delegate void DataEventHandler<TData>(DataFeed<TData> sender, TData data); 
} 

La declaración evento ahora se ve así:

public event DataEventHandler<TData> DataReady = delegate { }; 

Los beneficios de este enfoque:

  • firmas método tienen más semántica detalle. Usted sabe WHO está enviando LO QUE.
  • Strong-typing se conserva. No más casting object sender a lo que crees que debería ser.
  • No necesita new() levantar objetos y contaminar el montón, lo que puede ser problemático si su evento se dispara con frecuencia. Simplemente pase sus suscriptores exactamente lo que necesitan, ya sea una referencia de objeto o un tipo de valor.
  • Al utilizar la convención de nomenclatura ___EventHandler para sus delegados, aún promueve un estilo uniforme para su código, lo que facilita a los usuarios de su API saber cuál es su intención.

El único "inconveniente" es que dificulta a los usuarios de su código cablear su evento a los métodos existentes que tienen la firma object sender, EventArgs e. Sin embargo, este punto es discutible porque si su evento proporciona datos adicionales (por ejemplo, usted creó su propia subclase EventArgs), entonces tendrán que cambiar la firma del método de todos modos (o emitir a su tipo de subclase). De cualquier manera, eso sigue siendo desagradable.

Es por eso que me gusta mi camino.

Cuestiones relacionadas