[c#] ¿Hay algún inconveniente en agregar un delegado vacío anónimo en la declaración de evento?



Answers

En lugar de inducir una sobrecarga de rendimiento, ¿por qué no utilizar un método de extensión para aliviar ambos problemas?

public static void Raise(this EventHandler handler, object sender, EventArgs e)
{
    if(handler != null)
    {
        handler(sender, e);
    }
}

Una vez definido, nunca tendrá que volver a realizar otra prueba de evento nulo:

// Works, even for null events.
MyButtonClick.Raise(this, EventArgs.Empty);
Question

He visto algunas menciones de este modismo (incluso en SO ):

// Deliberately empty subscriber
public event EventHandler AskQuestion = delegate {};

El lado positivo es claro: evita la necesidad de buscar nulos antes de plantear el evento.

Sin embargo, estoy dispuesto a entender si hay inconvenientes. Por ejemplo, ¿es algo que se usa ampliamente y es lo suficientemente transparente como para no causar dolores de cabeza por mantenimiento? ¿Hay algún golpe de rendimiento apreciable de la llamada al suscriptor del evento vacío?




Si lo está haciendo a / lot /, es posible que desee tener un único delegado vacío, estático / compartido que reutilice, simplemente para reducir el volumen de instancias de delegado. Tenga en cuenta que el compilador guarda en caché este delegado por evento de todos modos (en un campo estático), por lo que es solo una instancia de delegado por definición de evento, por lo que no es un gran ahorro, pero tal vez valga la pena.

El campo por instancia en cada clase seguirá ocupando el mismo espacio, por supuesto.

es decir

internal static class Foo
{
    internal static readonly EventHandler EmptyEvent = delegate { };
}
public class Bar
{
    public event EventHandler SomeEvent = Foo.EmptyEvent;
}

Aparte de eso, parece estar bien.




En lugar del enfoque de "delegado vacío", se puede definir un método de extensión simple para encapsular el método convencional de comprobación del controlador de eventos frente a nulo. Se describe here y here .




Diría que es una construcción un poco peligrosa, porque te tienta a hacer algo como:

MyEvent(this, EventArgs.Empty);

Si el cliente lanza una excepción, el servidor la acompaña.

Entonces, tal vez lo haces:

try
{
  MyEvent(this, EventArgs.Empty);
}
catch
{
}

Pero, si tiene varios suscriptores y un suscriptor lanza una excepción, ¿qué ocurre con los otros suscriptores?

Para ese fin, he estado usando algunos métodos de ayuda estáticos que hacen la comprobación nula y se traga cualquier excepción del lado del suscriptor (esto es de idesign).

// Usage
EventHelper.Fire(MyEvent, this, EventArgs.Empty);


public static void Fire(EventHandler del, object sender, EventArgs e)
{
    UnsafeFire(del, sender, e);
}
private static void UnsafeFire(Delegate del, params object[] args)
{
    if (del == null)
    {
        return;
    }
    Delegate[] delegates = del.GetInvocationList();

    foreach (Delegate sink in delegates)
    {
        try
        {
            sink.DynamicInvoke(args);
        }
        catch
        { }
    }
}





Related