简体   繁体   English

两个Dispose实现之间的区别?

[英]Difference between two dispose implementations?

Is there a difference between these two implementations? 这两种实现之间有区别吗?

1 : 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 : 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. 值得注意的是,不能保证lambda表达式形式的事件处理程序根据实例和方法签名强制执行唯一性。 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 :-) 乔恩·斯凯特(Jon Skeet)详细回答了这一问题,它可能比我做得更好:-)

How to remove a lambda event handler 如何删除Lambda事件处理程序


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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM