2010-11-29 11 views
21

Duplicar posible:
Is there a downside to adding an anonymous empty delegate on event declaration?¿Es una buena práctica definir un cuerpo de delegado vacío para un evento?

¿Es una buena práctica para definir un cuerpo de delegados vacío para un evento para que usted no tiene que preocuparse plantear un evento que no tienen ningún controlador de eventos ? (no es necesario verificar si el evento es nulo).

código, como a continuación:

public event EventHandler<LoadEventArgs> LoadedData = delegate { }; 
+1

No todo el mundo está muy contento con esto, para más detalles, consulte aquí: http://stackoverflow.com/questions/9033/hidden-features-of-c/9282#9282 – gjvdkamp

Respuesta

36

ciertamente he encontró útil, sí. Habrá un pequeño y diminuto costo de rendimiento, pero el beneficio en legibilidad por no tener que realizar la prueba de nulidad hace que valga la pena IMO.

Vale la pena señalar que este es uno de los pocos momentos en que es bueno utilizar un método anónimo en lugar de una expresión lambda - de lo contrario hay que nombrar los parámetros que vas a ignorar, como esto:

public event EventHandler<LoadEventArgs> LoadedData = (sender, args) => {}; 

no me gusta tener que nombrar las cosas que no estoy con la intención de usar :)

+3

bueno, puede cay '(_, __) => {} 'que no está tan mal como' delegate {} ' –

+1

Ahora hay un?. operador que se puede usar en lugar de realizar comprobaciones nulas, p. MyEvent? .Invoke(); Puede ser una alternativa útil. – person27

+1

@ Anon234_4521: De hecho, según https: //codeblog.jonskeet.uk/2015/01/30/clean-event-handlers-invocation-with-c-6/- pero no voy a actualizar todas mis publicaciones de hace varios años :) –

4

yo no haría esto.

Existen dos motivos para esto. En primer lugar, es estándar simplemente verificar el controlador para null antes de llamar a esto. Ve esto por todos lados, en ejemplos, en la fuente de referencia de Microsoft y in the manuals.

En segundo lugar, la inicialización de sus eventos de esta manera asigna objetos innecesarios al crear su clase. Esto pondrá presión de memoria adicional en su aplicación sin una necesidad real. Esto se debe a:

public event EventHandler<LoadEventArgs> LoadedData = delegate { }; 

se traduce en:

public event EventHandler<LoadEventArgs> LoadedData = new EventHandler<LoadEventArgs>delegate { }); 

Si no lo hace ya, envolviendo sus eventos en los métodos específicos ayuda mucho:

public event EventHandler MyEvent; 

protected virtual void OnMyEvent(EventArgs e) 
{ 
    if (MyEvent != null) 
     MyEvent(this, e); 
} 

Usted puede hacer este hilo es seguro (r) usando lo siguiente:

public event EventHandler MyEvent; 

protected virtual void OnMyEvent(EventArgs e) 
{ 
    var handler = MyEvent; 

    if (handler != null) 
     handler(this, e); 
} 
+7

Creará un solo objeto extra que ser compartido por todas las instancias, porque el delegado no accede a ninguna variable capturada. (No está garantizado, pero el compilador de MS hará esto.) ¿Eso va a ser significativo? Lo dudo. Sin embargo, la posibilidad de que alguien escriba la versión no segura para subprocesos (según el primer fragmento de código) es bastante significativa, IMO. Si de hecho van a terminar con una NullReferenceException o no, quién sabe ... pero puedes apostar que sucederá en el sitio del cliente en lugar de en la prueba ... ¿vale la pena el código adicional la minúscula degradación del rendimiento? –

+1

@Jon Skeet - Eso depende. En primer lugar, la razón por la que agregué el segundo fragmento es específicamente por esa razón (creo que obtuve ese código de una respuesta anterior de usted :)). Sin embargo, la mayoría de las veces, las clases no son seguras para empezar. Tomemos por ejemplo 'Dictionary <,>'. No intente agregar y leer al mismo tiempo :). En cuanto al nuevo "delegado", tienes razón sobre eso. Sin embargo, se crea un nuevo 'EventHandler' para cada evento. 'MyEvent = delegate {}' se traduce en 'MyEvent = new EventHandler (delegate {})'. –

+0

Cada evento creará un objeto adicional, sí. A lo largo de toda la vida útil de la aplicación, creo que puedo manejar "desperdiciando" unos cientos de bytes para varios eventos. Tenga en cuenta que incluso si * no * le importa la seguridad de la secuencia, usar el truco "manejador no operativo" simplifica el código de generación de eventos ... y es una cosa menos en la que pensar si alguna vez quiere hacer el código seguro para hilos. –

1

Normalmente no uso C#, pero me parece una buena práctica. Esta es una aplicación de libro de texto del patrón 'Null Object'. Como se señaló, esto costará en términos de rendimiento cuando el delegado vacío realmente se ejecuta, pero gana en términos de rendimiento en cualquier otro momento, cuando no tiene que verificar un nulo explícito, por lo que también debería ser una ganancia neta. sabio siempre que la frecuencia de delegados vacíos sea baja.

Cuestiones relacionadas