[C#] Diferencia entre eventos y delegados y sus respectivas aplicaciones



Answers

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).

Question

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.




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.




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.




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.




Links