visual tutorial the studio example event delegate custom and c# events

tutorial - subscribe to the event c#



Evitar la misma asignaciĆ³n de controlador de eventos varias veces (4)

Si estoy asignando un controlador de eventos en tiempo de ejecución y está en un lugar que se puede llamar varias veces, ¿cuál es la práctica recomendada para evitar múltiples asignaciones del mismo controlador para el mismo evento?

object.Event += MyFunction

Agregar esto en un lugar que se llamará más de una vez ejecutará el controlador ''n'' veces (por supuesto).

He recurrido a eliminar cualquier controlador anterior antes de intentar agregar a través de

object.Event -= MyFunction; object.Event += MyFunction;

Esto funciona, pero parece estar fuera de alguna manera. Cualquier sugerencia sobre el manejo adecuado;) de este escenario.


¿Cuál es el modificador de acceso de ''objeto''?

Si es privado, solo debe preocuparse por el objeto contenedor que configura el controlador de eventos. Si es interno, solo necesita preocuparse por el conjunto contenedor que configura el controlador de eventos. Si es público, entonces está abierto de par en par.

Si ''object'' se puede hacer privado en la clase que lo contiene, puede hacer que sus cheques sean mucho más eficientes controlando la asignación del controlador de eventos en la clase local.

Si es '''' interno '''' o '''' público '''' y la singularidad un requisito, vaya con una clase contenedora que oculte '''' objetos '''' y exponga un método para asignar un manejador de eventos con sus controles detrás para garantizar la singularidad.


Baget tiene razón sobre el uso de un evento explícitamente implementado (aunque hay una mezcla de implementación de interfaz explícita y la sintaxis completa del evento). Probablemente puedas salirte con la tuya:

private EventHandler foo; public event EventHandler Foo { add { // First try to remove the handler, then re-add it foo -= value; foo += value; } remove { foo -= value; } }

Eso puede tener algunos casos extremos extraños si alguna vez agrega o elimina delegados de multidifusión, pero eso es poco probable. También necesita documentación cuidadosa, ya que no es la forma en que normalmente funcionan los eventos.


Puede implementar su propio almacenamiento de los delgados y verificar la exclusividad al agregarlos al evento. Consulte la clase EventOwner2 a continuación para ver un ejemplo. No sé cómo funciona esto en cuanto al rendimiento, pero eso no siempre es un problema.

using System; using System.Collections.Generic; namespace EventExperiment { class Program { static void Main(string[] args) { IEventOwner e=new EventOwner2(); Subscriber s=new Subscriber(e); e.RaiseSome(); Console.ReadKey(); } } /// <summary> /// A consumer class, subscribing twice to the event in it''s constructor. /// </summary> public class Subscriber { public Subscriber(IEventOwner eventOwner) { eventOwner.SomeEvent += eventOwner_SomeEvent; eventOwner.SomeEvent += eventOwner_SomeEvent; } void eventOwner_SomeEvent(object sender, EventArgs e) { Console.WriteLine(DateTimeOffset.Now); } } /// <summary> /// This interface is not essensial to this point. it is just added for conveniance. /// </summary> public interface IEventOwner { event EventHandler<EventArgs> SomeEvent; void RaiseSome(); } /// <summary> /// A traditional event. This is raised for each subscription. /// </summary> public class EventOwner1 : IEventOwner { public event EventHandler<EventArgs> SomeEvent = delegate { }; public void RaiseSome() { SomeEvent(this,new EventArgs()); } } /// <summary> /// A custom event. This is raised only once for each subscriber. /// </summary> public class EventOwner2 : IEventOwner { private readonly List<EventHandler<EventArgs>> handlers=new List<EventHandler<EventArgs>>(); public event EventHandler<EventArgs> SomeEvent { add { lock (handlers) if (handlers!=null&&!handlers.Contains(value)) { handlers.Add(value); } } remove { handlers.Remove(value); } } public void RaiseSome() { EventArgs args=new EventArgs(); lock(handlers) foreach (EventHandler<EventArgs> handler in handlers) { handler(this,args); } } } }


Tiendo a agregar un controlador de eventos en una ruta que se ejecuta una vez, por ejemplo, en un constructor.