2010-05-27 11 views
9

He estado investigando la gestión de memoria mucho recientemente y he estado viendo cómo se gestionan los eventos, ahora, estoy viendo la sintaxis explícita de agregar/eliminar para la suscripción al evento.Explicit Event add/remove, incomprendido?

Creo que es bastante simple, agregar/eliminar solo me permite realizar otra lógica cuando me suscribo y cancelo la suscripción? ¿Lo estoy entendiendo o hay más?

Además, mientras estoy aquí, cualquier consejo/mejores prácticas para limpiar mis identificadores de eventos.

Respuesta

3

Añadir/eliminar sintaxis se usa comúnmente para "reenviar" una implementación de evento a otra clase.

La limpieza de las suscripciones (no de los "controles de eventos") se realiza mejor implementando IDisposable.

ACTUALIZACIÓN: Hay alguna variación sobre qué objeto debe implementar IDisposable. El equipo de Rx tomó la mejor decisión desde el punto de vista del diseño: las suscripciones en sí son IDisposable. Los eventos .NET regulares no tienen un objeto que represente la suscripción, por lo que la elección se realiza entre el publicador (la clase en la que se define el evento) y el suscriptor (generalmente la clase que contiene la función miembro que se suscribe). Si bien mis instintos de diseño prefieren hacer que el suscriptor IDisposable, la mayoría de los códigos del mundo real hace que el editor IDisposable: es una implementación más fácil, y puede haber casos en los que no hay una instancia de suscriptor real.

(Es decir, si el código limpia realmente para arriba suscripciones de eventos en absoluto. La mayoría del código no lo hace.)

+0

Ha, me refiero a ellos como suscripciones al hablar con mis colegas, sin embargo, en el momento en que publico una pregunta, estoy usando la terminología equivocada. Gracias por la aclaración. – Hammerstein

6

Sí, el complemento/eliminar la sintaxis le permite implementar su propia lógica de suscripción. Cuando los excluyes (la notación estándar para un evento) el compilador genera implementaciones estándar. Eso es como las auto-propiedades.

En la siguiente muestra, no hay diferencia real entre Event1 y Event2.

public class Foo 
{ 
    private EventHandler handler; 
    public event EventHandler Event1 
    { 
    add { handler += value; } 
    remove { handler -= value; } 
    } 

    public event EventHandler Event2; 
} 

Pero este es un tema aparte de los controladores de 'limpieza'. Es la clase de suscripción la que debe cancelar la suscripción. La clase editorial no puede ayudar con esto mucho.
Imagina una clase que "limpiaría" la lista de suscripción de sus eventos. Solo puede hacer esto con sensatez cuando está Dispuesto, y entonces es poco probable que sea productivo ya que una clase Dispuesta generalmente se vuelve coleccionable poco después de que se Disipe.

+1

Creo que un usuario final no podría: 'Foo foo = ...; foo.Event1 (sender, e); 'pero podría hacer' foo.Event2 (null, null); '. – user7116

+0

Gracias por el ejemplo y la aclaración. ¡Pensé que lo tenía, pero ya estaba pensando! Voy a publicar mi pregunta sobre la gestión de la memoria en una pregunta separada, ya que creo que hay más que quiero preguntar. – Hammerstein

+0

Me equivoco, recibe un error en ambos casos, pero recibe uno diferente en el segundo caso, 'error CS0070: el evento 'Program.Foo.Event2' solo puede aparecer en el lado izquierdo de + = o - = (excepto cuando se usa dentro del tipo 'Program.Foo') '. – user7116

9

Las propiedades de agregar/quitar son básicamente de la misma lógica de usar propiedades set/get con otros miembros. Le permite crear una lógica extra al registrarse para un evento, y encapsula el evento en sí.

Un buen ejemplo de por qué quieres hacerlo, es detener el cómputo adicional cuando no es necesario (nadie está escuchando el evento).

Por ejemplo, digamos que los eventos se desencadenan por un temporizador, y no queremos que el tiempo funcione si nadie se registrará en el evento:

private System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer(); 
private EventHandler _explicitEvent; 
public event EventHandler ExplicitEvent 
{ 
    add 
    { 
     if (_explicitEvent == null) timer.Start(); 
     _explicitEvent += value; 
    } 
    remove 
    { 
     _explicitEvent -= value; 
     if (_explicitEvent == null) timer.Stop(); 
    } 
} 

Usted probablemente querrá bloquear el agregar/eliminar con un objeto (una idea de último momento) ...