¿Diferencia entre dos implementaciones de eliminación?

¿Hay alguna diferencia entre estas dos implementaciones?

1:

public class SMSManager : ManagerBase
{
    private EventHandler<SheetButtonClickEventArgs> _buttonClickevent; 

    public SMSManager(DataBlock smsDataBlock, DataBlock telephonesDataBlock) :
        base(smsDataBlock)
    {
        _buttonClickevent = new EventHandler<SheetButtonClickEventArgs>(OnButtonClick);
        SheetEvents.ButtonClick += _buttonClickevent;

    }

    public override void Dispose()
    {
        base.Dispose();
        if (_buttonClickevent != null)
        SheetEvents.ButtonClick -= _buttonClickevent;
    }
}

2:

public class SMSManager : ManagerBase
{
    public SMSManager(DataBlock smsDataBlock, DataBlock telephonesDataBlock) :
        base(smsDataBlock)
    {
        SheetEvents.ButtonClick += new EventHandler<SheetButtonClickEventArgs>(OnButtonClick);   
    }

    public override void Dispose()
    {
        base.Dispose();
        SheetEvents.ButtonClick -= new EventHandler<SheetButtonClickEventArgs>(OnButtonClick);
    }
}

El primero parece ser más correcto que el segundo en lo que respecta a las fugas de memoria. ¿Pero es realmente correcto?

preguntado el 22 de mayo de 12 a las 16:05

No olvides marcar una respuesta como respuesta, ayuda a enriquecer el contenido de este sitio. -

1 Respuestas

En resumidas cuentas, el segundo fragmento de código es correcto y seguro (incluso si no hay controladores registrados).

Considere esta aplicación de muestra:

namespace ConsoleApplication61
{
    class Program
    {
        static void Main(string[] args)
        {
            var f = new Foo();
            f.MyEvent += new EventHandler(Handler);
            f.Trigger();
            f.MyEvent -= new EventHandler(Handler);
            f.Trigger();
            Console.Read();
        }

        static void Handler(object sender, EventArgs e)
        {
            Console.WriteLine("handled");
        }
    }

    class Foo
    {
        public event EventHandler MyEvent;
        public void Trigger()
        {
            if (MyEvent != null)
                MyEvent(null, null);
        }
    }
}

Esta muestra imprime "manejado" una vez.

Entonces, en su ejemplo, son funcionalmente iguales y ambos funcionarán según sea necesario. Eliminar un controlador que no se ha agregado también es una acción segura, simplemente no encuentra nada para eliminar y no hace nada.

Como se proporciona en los comentarios, la respuesta de Marc entra en más detalles:

Anular el registro de eventos con una nueva instancia del delegado


Controladores de eventos con métodos anónimos

Vale la pena señalar que no se garantiza que los controladores de eventos en forma de expresiones lambda impongan la exclusividad en función de la firma de la instancia y el método. Si necesita cancelar la suscripción de un método anónimo, debe promoverlo a un método o mantener una referencia al método anónimo para su uso posterior:

Func<object, EventArgs> meth = (s, e) => DoSomething();

myEvent += meth;
myEvent -= meth;

Jon Skeet entra en detalles al responder esto y probablemente lo haga mejor que yo :-)

Cómo eliminar un controlador de eventos lambda


Una ligera refactorización

Refactorizaría lo siguiente:

public class SMSManager : ManagerBase
{
    public SMSManager(DataBlock smsDataBlock, DataBlock telephonesDataBlock) 
        : base(smsDataBlock)
    {
        SheetEvents.ButtonClick += OnButtonClick;   
    }

    public override void Dispose()
    {
        SheetEvents.ButtonClick -= OnButtonClick;
        base.Dispose();
    }
}

contestado el 23 de mayo de 17 a las 11:05

@SwDevMan81 ¡Bingo! He estado buscando esa información, ta. - adam houldsworth

Es por eso que todos andamos por aquí :) Siempre aprendiendo cosas nuevas - SwDevMan81

@All Lo interesante son los controladores de eventos con métodos anónimos (la nueva moda), no juegan a la pelota tan bien. Solo aprendí esto el otro día. - adam houldsworth

@SwDevMan81 El único (y único) problema de aprender cosas nuevas en este sitio es el tiempo que se tarda en revisar el código antiguo (o el código escrito ayer) para ver si cometiste el error que no sabías en ese momento jajaja! La cantidad de veces que sucede esto... - adam houldsworth

@Adam - Jaja cierto. Tengo 666 respuestas, así que dejo que el viejo y malvado código viva :P - SwDevMan81

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.