Difference between two dispose implementations?

Is there a difference between these two implementations?

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);
    }
}

The first one seems to be more correct than the second in regards to memory leaks. But is it really correct?


The long and short of it is the second piece of code is correct and safe (even if there are no handlers registered).

Consider this sample app:

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);
        }
    }
}

This sample prints "handled" once.

So in your example, they are functionally the same and both will work as needed. Removing a handler that hasn't been added is also a safe action, it simply finds nothing to remove and does nothing.

As provided in the comments, Marc's answer goes into more detail:

Unregister events with new instance of the delegate


Event Handlers with Anonymous Methods

It is worth noting that event handlers in the form of lambda expressions are not guaranteed to enforce uniqueness based on instance and method signature. If you need to unsubscribe an anonymous method, you either need to promote it to a method or keep a reference to the anonymous method for later use:

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

myEvent += meth;
myEvent -= meth;

Jon Skeet goes into detail answering this and likely does a better job of it than me :-)

How to remove a lambda event handler


A Slight Refactoring

I would refactor to the following:

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

    public override void Dispose()
    {
        SheetEvents.ButtonClick -= OnButtonClick;
        base.Dispose();
    }
}
链接地址: http://www.djcxy.com/p/51454.html

上一篇: 所有的jquery事件都应该绑定到$(document)吗?

下一篇: 两个dispose实现之间的区别?