2011-11-03 23 views
5

Considere la situación en la que desea suscribirse a un evento para una y única notificación. Una vez que llega la primera notificación, se da de baja de todos los eventos futuros. ¿El siguiente patrón presentará algún problema de memoria? Funciona, pero no estaba seguro de si el cierre autorreferencial podría mantener las cosas en la memoria más tiempo de lo deseado.¿El siguiente patrón de cancelar su suscripción a un evento por cierre podría causar algún problema?

public class Entity 
{ 
    public event EventHandler NotifyEvent; 
} 

// And then, elsewhere, for a listen-once handler, we might do this: 
Entity entity = new Entity(); 
Action<object, EventArgs> listener = null; 
listener = (sender, args) => 
{ 
    // do something interesting 
    // unsubscribe, so we only get 1 event notification 
    entity.NotifyEvent -= new EventHandler(listener); 
}; 
entity.NotifyEvent += new EventHandler(listener); 

Tenga en cuenta que usted tiene que declarar 'oyente' y asignar un valor (nulo). De lo contrario, el compilador se queja de 'Uso de la variable local no asignada listener'

+0

Es posible hacer que el código sea más expresiva encerrando la parte del código que empieza con 'Acción oyente = null;' llaves. Pero no estoy seguro de si esto haría la vida más fácil para el recolector de basura: ¡después de todo, de todos modos, ya no usa su variable! – Vlad

Respuesta

6

No hay nada de malo en este patrón. Es el mismo patrón que yo y muchos otros utilizan para asignar y eliminar una expresión lambda a un controlador de eventos.

+0

Una pregunta sobre este código: ¿Se podría usar el remitente para anular la suscripción? Algo así como (emisor como entidad) .NotifyEvent - = new EventHandler (listener) también dentro de la expresión lamba, o podría ser algún problema secundario? –

+0

@RickyAH posiblemente. Funcionaría para algunos tipos aunque no recomendaría hacerlo. En general, soy muy cauteloso de confiar en la parte 'remitente' del patrón de evento. Es útil a veces, pero en general, supongo que es un valor poco fiable – JaredPar

+0

gracias por los comentarios. –

4

Si bien creo que el patrón general está bien, no pasaría por Action<object, EventArgs>. Que haría uso:

EventHandler listener = null; 
listener = (sender, args) => 
{ 
    // do something interesting 
    // unsubscribe, so we only get 1 event notification 
    entity.NotifyEvent -= listener; 
}; 
entity.NotifyEvent += listener; 
+0

Gracias por la sugerencia. De todos modos, en general uso delegados de eventos personalizados de todos modos, pero para el ejemplo, solo utilicé EventHandler como el delegado del evento, ya que más personas lo reconocen. Completamente espaciado en Action though, así que gracias. (Sin embargo, dejaré mi ejemplo menos que ideal para dar tu contexto de respuesta) – Matt

Cuestiones relacionadas