No veo ventajas de usar eventos sobre delegados, aparte de ser azúcar sintáctico. Quizás estoy entendiendo mal, pero parece que el evento es solo un marcador de posición para delegado.
¿Me explicarías las diferencias y cuándo usar cuál? ¿Cuáles son las ventajas y desventajas? Nuestro código está fuertemente arraigado con eventos, y quiero llegar al fondo.
¿Cuándo usaría delegados en eventos y viceversa? Indique su experiencia en el mundo real con ambos, digamos en el código de producción.
Respuestas:
Desde el punto de vista técnico, otras respuestas han abordado las diferencias.
Desde una perspectiva semántica, los eventos son acciones provocadas por un objeto cuando se cumplen ciertas condiciones. Por ejemplo, mi clase de Acciones tiene una propiedad llamada Límite y genera un evento cuando los precios de las acciones alcanzan el Límite. Esta notificación se realiza mediante un evento. Si alguien realmente se preocupa por este evento y se suscribe, está más allá de la preocupación de la clase propietaria.
Un delegado es un término más genérico para describir una construcción similar a un puntero en términos de C / C ++. Todos los delegados en .Net son delegados de multidifusión. Desde una perspectiva semántica, generalmente se utilizan como una especie de entrada. En particular, son una forma perfecta de implementar el Patrón de estrategia . Por ejemplo, si quiero ordenar una lista de objetos, puedo proporcionar una estrategia de comparación al método para decirle a la implementación cómo comparar dos objetos.
He utilizado los dos métodos en el código de producción. Muchos de mis objetos de datos notifican cuando se cumplen ciertas propiedades. El ejemplo más básico, cada vez que cambia una propiedad, se genera un evento PropertyChanged (consulte la interfaz INotifyPropertyChanged). He usado delegados en código para proporcionar diferentes estrategias de convertir ciertos objetos en cadenas. Este ejemplo en particular fue una lista ToString () glorificada de implementaciones para un tipo de objeto particular para mostrarlo a los usuarios.
fuente
La palabra clave
event
es un modificador de alcance para delegados de multidifusión. Las diferencias prácticas entre esto y simplemente declarar un delegado de multidifusión son las siguientes:event
en una interfaz.public event
. Ej .).Como cuestión de interés, puede aplicar
+
y-
a los delegados de multidifusión, y esta es la base de la sintaxis+=
y-=
para la asignación combinada de delegados a eventos. Estos tres fragmentos son equivalentes:Ejemplo dos, que ilustra tanto la asignación directa como la asignación combinada.
Ejemplo tres: sintaxis más familiar. Probablemente esté familiarizado con la asignación de nulo para eliminar todos los controladores.
Como las propiedades, los eventos tienen una sintaxis completa que nadie usa. Esta:
... hace exactamente lo mismo que esto:
Los métodos de agregar y quitar son más notorios en la sintaxis bastante rígida que usa VB.NET (sin sobrecargas de operadores).
fuente
Los eventos son azúcar sintáctico. Son deliciosos. Cuando veo un evento, sé qué hacer. Cuando veo a un delegado, no estoy tan seguro.
La combinación de eventos con interfaces (más azúcar) lo convierte en un bocadillo delicioso. Los delegados y las clases abstractas virtuales puras son mucho menos apetecibles.
fuente
Los eventos se marcan como tales en los metadatos. Esto permite que elementos como los diseñadores de Windows Forms o ASP.NET distingan eventos de meras propiedades de tipo delegado y proporcionen el soporte adecuado para ellos (mostrándolos específicamente en la pestaña Eventos de la ventana Propiedades).
Otra diferencia con una propiedad de tipo delegado es que los usuarios solo pueden agregar y eliminar controladores de eventos, mientras que con una propiedad de tipo delegado pueden establecer el valor:
Esto ayuda a aislar a los suscriptores de eventos: puedo agregar mi controlador a un evento, y usted puede agregar su controlador al mismo evento, y no sobrescribirá accidentalmente mi controlador.
fuente
Aunque los eventos se implementan normalmente con delegados de multidifusión, no es necesario que se utilicen de esa manera. Si una clase expone un evento, eso significa que la clase expone dos métodos. Sus significados son, en esencia:
La forma más común para que una clase maneje un evento que expone es definir un delegado de multidifusión y agregar / eliminar cualquier delegado que se pase a los métodos anteriores, pero no es necesario que funcionen de esa manera. Desafortunadamente, la arquitectura de eventos no logra hacer algunas cosas que habrían hecho que los enfoques alternativos fueran mucho más limpios (por ejemplo, hacer que el método de suscripción devuelva un MethodInvoker, que sería guardado por el suscriptor; para cancelar la suscripción de un evento, simplemente invoque el método devuelto) por lo que los delegados de multidifusión son, con mucho, el enfoque más común.
fuente
para entender las diferencias puedes mirar estos 2 ejemplos
Ejemplo con delegados (acción en este caso que es un tipo de delegado que no devuelve valor)
para usar el delegado debes hacer algo como esto
este código funciona bien, pero podría tener algunos puntos débiles.
Por ejemplo si escribo esto
con la última línea de código había anulado los comportamientos anteriores solo con uno faltante
+
(he usado en+
lugar de+=
)Otro punto débil es que cada clase que usa tu
Animal
clase puede subirRaiseEvent
simplemente llamándolaanimal.RaiseEvent()
.Para evitar estos puntos débiles, puede utilizar
events
en c #.Tu clase de Animal cambiará de esta manera
llamar eventos
Diferencias:
notas
EventHandler se declara como el siguiente delegado:
toma un remitente (de tipo Objeto) y argumentos de evento. El remitente es nulo si proviene de métodos estáticos.
También puede usar
EventHAndler
en su lugar este ejemplo que usaEventHandler<ArgsSpecial>
consulte aquí para obtener documentación sobre EventHandler
fuente
Cuando diseño mis propias API, defino delegados que se pasan como parámetros a métodos o constructores de clases:
Predicate
yAction
se pasan a las clases de colección genéricas .Net)Estos delegados generalmente no son opcionales en tiempo de ejecución (es decir, no deben serlo
null
).Tiendo a no usar eventos; pero cuando utilizo eventos, los uso para señalar opcionalmente eventos a cero, uno o más clientes que podrían estar interesados, es decir, cuando tiene sentido que una clase (por ejemplo, la
System.Windows.Form
clase) debería existir y ejecutarse si algún cliente tiene o no agregó un controlador de eventos a su evento (por ejemplo, existe el evento 'mouse down' del formulario, pero es opcional si algún cliente externo está interesado en instalar un controlador de eventos en ese evento).fuente
Aunque no tengo razones técnicas para ello, utilizo eventos en el código de estilo de la interfaz de usuario, en otras palabras, en los niveles superiores del código, y uso delegados para la lógica que se encuentra más profunda en el código. Como digo, podría usar cualquiera de los dos, pero encuentro que este patrón de uso es lógicamente sólido, por lo menos, ayuda a documentar los tipos de devoluciones de llamada y su jerarquía también.
Editar: Creo que la diferencia en los patrones de uso que tengo sería que, me parece perfectamente aceptable ignorar los eventos, son ganchos / stubs, si necesita saber sobre el evento, escúchelos, si no le importa el evento simplemente ignórelo. Es por eso que los uso para la interfaz de usuario, una especie de estilo de evento de Javascript / navegador. Sin embargo, cuando tengo un delegado, espero REALMENTE esperar que alguien maneje la tarea del delegado y lanzar una excepción si no se maneja.
fuente
La diferencia entre eventos y delegados es mucho menor de lo que solía pensar. Acabo de publicar un video supercorto en YouTube sobre el tema: https://www.youtube.com/watch?v=el-kKK-7SBU
¡Espero que esto ayude!
fuente
fuente