usar una que programacion librería funcion eventos evento event ejemplos delegados delegado crear como biblioteca c# design events delegates

c# - una - Diferencia entre eventos y delegados y sus respectivas aplicaciones



que es un evento en programacion (9)

No veo ventajas de usar eventos sobre delegados, aparte de ser azúcar sintáctica. Tal vez estoy malinterpretando, pero parece que ese evento es solo un marcador de posición para el delegado.

¿Me explicarías las diferencias y cuándo usarlas? ¿Cuáles son las ventajas y desventajas? Nuestro código está muy arraigado con los eventos, y quiero llegar al fondo del mismo.

¿Cuándo usarías delegados sobre eventos y viceversa? Por favor, indique su experiencia en el mundo real con ambos, por ejemplo, en el código de producción.


Editar # 1 ¿ Cuándo usarías delegados sobre eventos y vs.versa? Por favor, indique su experiencia en el mundo real con ambos, por ejemplo, en el código de producción.

Cuando diseño mis propias API, defino delegados que se pasan como parámetros a los métodos, o a los constructores de las clases:

  • De modo que un método puede implementar un patrón simple de ''método de plantilla'' (como, por ejemplo, los delegados de Predicate y Action se pasan a las clases de colección genéricas de .Net)
  • O para que la clase pueda hacer una "devolución de llamada" (por lo general, una devolución de llamada a un método de la clase que lo creó).

Estos delegados generalmente no son opcionales en tiempo de ejecución (es decir, no deben ser null ).

Tiendo a no usar eventos; pero cuando utilizo eventos, los utilizo 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 clase System.Windows.Form ) debería existir y ejecutarse ya sea o no, ningún cliente ha agregado un controlador de eventos a su evento (por ejemplo, existe el evento ''mouse down'' del formulario, pero es opcional si un cliente externo está interesado en instalar un controlador de eventos en ese evento).


Aunque los eventos se implementan típicamente con delegados de multidifusión, no es obligatorio 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:

  1. Aquí hay un delegado. Por favor, invoca cuando sucede algo interesante.
  2. Aquí hay un delegado. Debería destruir toda referencia al mismo tan pronto como sea conveniente (y no volver a llamarlo).

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 transfiera a los métodos anteriores, pero no es obligatorio que funcionen de esa manera. Desafortunadamente, la arquitectura del evento falla en hacer algunas cosas que hubieran hecho los enfoques alternativos mucho más limpios (ej. Hacer que el método de suscripción devuelva un MethodInvoker, que el suscriptor guardara, cancelar la suscripción a un evento, simplemente invocar el método devuelto) para que los delegados multicast son de lejos el enfoque más común.


Aunque no tengo razones técnicas para ello, uso eventos en el código de estilo de UI, en otras palabras, en los niveles superiores del código, y uso delegados para la lógica que se adentra más en el código. Como ya he dicho, podría usar cualquiera de estas dos opciones, pero creo que este patrón de uso es lógicamente correcto, si no es así, también ayuda a documentar los tipos de devolución de llamada y su jerarquía.

Editar: Creo que la diferencia en los patrones de uso que tengo es que, me parece perfectamente aceptable ignorar los eventos, son ganchos / talones, si necesita saber sobre el evento, escúchelos, si no le importa el evento simplemente lo ignora. Es por eso que los uso para UI, tipo de evento de Javascript / Navegador. Sin embargo, cuando tengo un delegado, espero REALMENTE esperar que alguien se encargue de la tarea del delegado y lanzar una excepción si no se maneja.


Desde el punto de vista técnico, otras respuestas han abordado las diferencias.

Desde una perspectiva semántica, los eventos son acciones planteadas por un objeto cuando se cumplen ciertas condiciones. Por ejemplo, mi clase Stock 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 a través de 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 usan 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 usado los dos métodos en el código de producción. Toneladas de mis objetos de datos notifican cuando se cumplen ciertas propiedades. El ejemplo más básico, cuando una propiedad cambia, se genera un evento PropertyChanged (vea la interfaz INotifyPropertyChanged). He usado delegados en el código para proporcionar diferentes estrategias para convertir ciertos objetos en cadenas. Este ejemplo particular fue una lista glorificada de ToString () de implementaciones para un tipo de objeto particular para mostrarlo a los usuarios.


La diferencia entre los eventos y los delegados es mucho más pequeña de lo que solía pensar. Acabo de publicar un video súper corto de YouTube sobre el tema: https://www.youtube.com/watch?v=el-kKK-7SBU

¡Espero que esto ayude!


Los eventos se marcan como tales en los metadatos. Esto permite que elementos como los diseñadores de Windows Forms o ASP.NET distingan los eventos de las meras propiedades del tipo de delegado y proporcionen el soporte adecuado para ellos (mostrándolos específicamente en la pestaña Eventos de la ventana Propiedades).

Otra diferencia de una propiedad de tipo delegado es que los usuarios solo pueden agregar y eliminar manejadores de eventos, mientras que con una propiedad de tipo delegado pueden establecer el valor:

someObj.SomeCallback = MyCallback; // okay, replaces any existing callback someObj.SomeEvent = MyHandler; // not okay, must use += instead

Esto ayuda a aislar a los suscriptores del evento: puedo agregar mi controlador a un evento, y puedes agregar tu controlador al mismo evento, y no sobreescribirás accidentalmente mi controlador.


Los eventos son azúcar sintáctico. Son deliciosos. Cuando veo un evento, sé qué hacer. Cuando veo un delegado, no estoy tan seguro.

La combinación de eventos con interfaces (más azúcar) lo convierte en un tentempié delicioso. Los delegados y las clases abstractas virtuales puras son mucho menos apetecibles.


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)

public class Animal { public Action Run {get; set;} public void RaiseEvent() { if (Run != null) { Run(); } } }

para usar el delegado deberías hacer algo como esto

Animale animal= new Animal(); animal.Run += () => Console.WriteLine("I''m running"); animal.Run += () => Console.WriteLine("I''m still running") ; animal.RaiseEvent();

este código funciona bien, pero podrías tener algunos puntos débiles.

Por ejemplo, si escribo esto

animal.Run += () => Console.WriteLine("I''m running"); animal.Run += () => Console.WriteLine("I''m still running"); animal.Run = () => Console.WriteLine("I''m sleeping") ;

con la última línea de código anulé los comportamientos previos solo con un + faltante (he usado + lugar de += )

Otro punto débil es que cada clase que use su clase Animal puede generar RaiseEvent llamándolo animal.RaiseEvent() .

Para evitar estos puntos débiles puedes usar events en c #.

Tu clase de Animal cambiará de esta manera

public class ArgsSpecial :EventArgs { public ArgsSpecial (string val) { Operation=val; } public string Operation {get; set;} } public class Animal { public event EventHandler<ArgsSpecial> Run = delegate{} //empty delegate. In this way you are sure that value is always != null because no one outside of the class can change it public void RaiseEvent() { Run(this, new ArgsSpecial("Run faster")); } }

llamar eventos

Animale animal= new Animal(); animal.Run += (sender, e) => Console.WriteLine("I''m running. My value is {0}", e.Operation); animal.RaiseEvent();

Diferencias

  1. No está utilizando una propiedad pública sino un campo público (con eventos el compilador protege sus campos del acceso no deseado)
  2. Los eventos no se pueden asignar directamente. En este caso, no puede hacer el error anterior que he mostrado al anular el comportamiento.
  3. Nadie fuera de tu clase puede plantear el evento.
  4. Los eventos se pueden incluir en una declaración de interfaz, mientras que un campo no puede

notas

EventHandler se declara como el siguiente delegado:

public delegate void EventHandler (object sender, EventArgs e)

toma un remitente (del tipo de objeto) y argumentos de evento. El remitente es nulo si proviene de métodos estáticos.

También puede utilizar EventHAndler en este ejemplo que use EventHandler<ArgsSpecial>

consulte here documentación sobre EventHandler


El event palabra clave 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:

  • Puede usar event en una interfaz.
  • El acceso de invocación al delegado de multidifusión está limitado a la clase declarante. El comportamiento es como si el delegado fuera privado para la invocación. A los efectos de la asignación, el acceso es tal como lo especifica un modificador de acceso explícito (por ejemplo, public event ).

Como cuestión de interés, puede aplicar + y - a delegados de multidifusión, y esta es la base de la sintaxis += y -= para la asignación de combinación de delegados a eventos. Estos tres fragmentos son equivalentes:

B = new EventHandler(this.MethodB); C = new EventHandler(this.MethodC); A = B + C;

Muestra dos, que ilustra tanto la asignación directa como la asignación de combinación.

B = new EventHandler(this.MethodB); C = new EventHandler(this.MethodC); A = B; A += C;

Muestra tres: sintaxis más familiar. Probablemente esté familiarizado con la asignación de null para eliminar todos los controladores.

B = new EventHandler(this.MethodB); C = new EventHandler(this.MethodC); A = null; A += B; A += C;

Al igual que las propiedades, los eventos tienen una sintaxis completa que nadie usa. Esta:

class myExample { internal EventHandler eh; public event EventHandler OnSubmit { add { eh = Delegate.Combine(eh, value) as EventHandler; } remove { eh = Delegate.Remove(eh, value) as EventHandler; } } ... }

... hace exactamente lo mismo que esto:

class myExample { public event EventHandler OnSubmit; }

Los métodos de agregar y quitar son más conspicuos en la sintaxis bastante rígida que usa VB.NET (sin sobrecargas del operador).