2010-10-07 11 views
29

Odio EventHandler. Odio tener que lanzar el sender si quiero hacer algo con él. Odio tener que hacer una nueva clase heredando desde EventArgs para usar EventHandler<T>.Por qué * debería * usamos EventHandler

Siempre me han dicho que EventHandler es la tradición y bla, bla ... lo que sea. Pero no puedo encontrar una razón por la cual este dogma todavía esté presente.

¿Existe una razón por la que sería una mala idea para hacer un nuevo delegado:

delegate void EventHandler<TSender, T>(TSender sender, T args); 

De esta forma el sender será typesafe y puede pasar cualquier cosa diablos quiero que los argumentos (incluida la costumbre EventArgs si así lo deseo).

+0

Entonces también puede utilizar Action como su delegado. –

+0

Sí, es muy cierto, por lo que ampliaré mi pregunta: ¿por qué no utilizar Action ? – RichK

Respuesta

24

En realidad, hay una buena razón para requerir que el segundo argumento derive de EventArgs si su código totalmente confiable hospeda el código de terceros como parcialmente de confianza.

Como la devolución de llamada al delegado encargado de la gestión de eventos se realiza en el contexto del código ascendente y no del código de terceros, es posible que el código malintencionado de terceros agregue una operación privilegiada del sistema como controlador de eventos y potencialmente ejecute una escalada de ataque de privilegios ejecutando código en su contexto de plena confianza para que su contexto parcialmente confiable no pueda ejecutarse.

Por ejemplo, si declara un controlador como tipo int -> void, el código de tercero podría enrutar YourEvent += Enviroment.Exit(-1) y hacer que salga del proceso involuntariamente. Obviamente, esto causaría un problema fácil de detectar, pero hay muchas más API malintencionadas que podrían ponerse en cola para hacer otras cosas.

Cuando la firma es (object, EventArgs) -> void, no hay operaciones privilegiadas en el marco que se puedan enrutar porque ninguna de ellas es compatible con esta firma. Es parte de la revisión del código de seguridad en el marco para garantizar esto (desafortunadamente no puedo encontrar la fuente donde lo leí).

Por lo tanto, en determinadas circunstancias, existen motivos de seguridad válidos sobre por qué debe utilizar el patrón estándar. Si está 100% seguro de que su código nunca se utilizará en estas circunstancias, entonces la guía de firmas de eventos no es tan importante (aparte de que otros desarrolladores piensen en WTF), pero si es así, debería seguirla.

+2

+1 Wow. Buen post. Este es el tipo de publicaciones que me mantienen volviendo a SO. – NotMe

+0

Muy muy interesante. Me encanta saber si esto fue en el diseño original o la convención se cayó o el uso. –

+1

Aunque esta es una respuesta válida con el estado actual de las cosas, parece que sería mucho mejor si el código que no debería llamar a Exit (o pasarlo para ser llamado) ni siquiera fuera capaz de acceder a Exit en el primer lugar. –

9

No hay ninguna razón para usarlo además de es la convención .net aceptada y cualquiera que lea su código debe entenderlo con bastante facilidad. Para esto, es una buena razón.

Sin embargo, es su código y usted puede decidir lo mejor para usted. Por supuesto, a medida que interactúa con el fcl tendrá que hacerlo a su manera utilizando controladores de eventos.

+0

Acepto, se acepta que cualquier codificador C# reconocería. –

+6

Una vez dicho esto, un delegado fuertemente tipado también sería reconocido :) –

+0

No veo por qué los desarrolladores podrían confundirse por el código del OP. Sin embargo, +1 por señalar lo obvio: es su código para hacer lo que quiera. – NotMe

0

Como dijo Preet Sangha, la razón por la cual crear un delegado de ese tipo sería una mala idea es que a otros desarrolladores podría confundirse por qué lo haces de esa manera.

Usando EventHandler delegado es una guía que se presenta aquí: http://msdn.microsoft.com/en-us/library/ms229011.aspx

+5

Podría argumentar, sin embargo, que si utiliza, por ejemplo, 'Acción <...>' como su controlador de eventos es suficiente para confundir a un miembro del equipo, su equipo ya tiene problemas mayores. ;) – jalf

+0

He estado programando durante 20 años, los últimos 10 años en C# y me confundiría, pero entonces el objetivo de las tiendas más avanzadas de hoy parece ser utilizar los diseños más complicados posibles, no utilizar enfoques simples. –

+0

Han pasado 6 años desde que publiqué esa respuesta y me quedo totalmente al margen de mi declaración. Hay muchos desarrolladores sin experiencia, algunos desarrolladores que cambiaron idiomas, algunos todavía son juniors, pero todavía se necesitan en proyectos, etc., así que cuando tomas un desarrollador promedio no siempre terminas con los más brillantes gente en la tierra Seguramente es mejor trabajar en una compañía que solo contrata la crème de la crème, pero en realidad es mejor esperar que alguien se confunda por cosas como esa. Incluso la gente experimentada podría. Y el objetivo final debería ser la preparación del código. – prostynick

6

comúnmente utilizo Action<...> tipos como controladores de eventos - si no es necesario INTEROP con otro código (o un diseñador) que requiere específicamente EventHandler, hay no hay razón para usarlo.

2

Bueno, hacer todo ese casting es inusual, el código del cliente con bastante frecuencia ya sabe quién es el emisor porque suscribió explícitamente el evento para un solo objeto. Compartir manejadores de eventos es bastante raro. Si el comportamiento común es deseable, entonces el mejor enfoque es derivar de la clase y anular el método OnXxxx. A continuación, ya no se preocupa por emisor, tiene este.

Pero resuelva su problema trivialmente incluyendo una referencia de tipo seguro para el remitente en su clase derivada de EventArgs personalizada.

+1

no estoy de acuerdo con usted. por ejemplo, el código de cliente puede tener solo un controlador en la matriz de objetos. – void

+0

Hmya, eso es "hada raro". –

2

Estoy de acuerdo con usted, la convención es estúpida y/o anticuada. Hágalo de la manera correcta, con la seguridad adecuada y los genéricos.

Pasa todo el tiempo que tienes una tarea que hacer, y puedes seguir la forma en que lo hizo el último o hacerlo de otra manera que crees que es probablemente mejor.

Generalmente se elige la primera opción: hazlo igual que el último tipo, y no te meterás en problemas. Pero la segunda opción es la que mejora el software a largo plazo. (O al menos PUEDE mejorarlo, si está en lo cierto que su camino es mejor! :))