这两种实现之间有区别吗?

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

关于内存泄漏,第一个似乎比第二个更正确。但这真的正确吗?

最佳答案

总之,第二段代码是正确且安全的(即使没有注册处理程序)。

考虑以下示例应用程序:

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

此样本仅打印一次“已处理”。

因此,在您的示例中,它们在功能上相同,并且都可以根据需要工作。删除未添加的处理程序也是安全的操作,它只是发现没有要删除的内容,也不执行任何操作。

正如评论中所提供的,马克的答案更加详细:

Unregister events with new instance of the delegate

具有匿名方法的事件处理程序

值得注意的是,不能保证lambda表达式形式的事件处理程序根据实例和方法签名强制执行唯一性。如果需要取消订阅匿名方法,则需要将其升级为方法或保留对匿名方法的引用以供以后使用:
Func<object, EventArgs> meth = (s, e) => DoSomething();

myEvent += meth;
myEvent -= meth;

乔恩·斯凯特(Jon Skeet)详细回答了这一问题,并且可能会比我做得更好:-)

How to remove a lambda event handler

少量重构

我将重构为以下内容:
public class SMSManager : ManagerBase
{
    public SMSManager(DataBlock smsDataBlock, DataBlock telephonesDataBlock)
        : base(smsDataBlock)
    {
        SheetEvents.ButtonClick += OnButtonClick;
    }

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

关于c# - 两个Dispose实现之间的区别?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/10704710/

10-12 14:55