5

这两种实现有区别吗?

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

在内存泄漏方面,第一个似乎比第二个更正确。但它真的正确吗?

4

1 回答 1

5

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

考虑这个示例应用程序:

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

此示例打印“已处理”一次。

因此,在您的示例中,它们在功能上是相同的,并且都可以根据需要工作。删除尚未添加的处理程序也是一个安全的操作,它只是找不到要删除的内容并且什么也不做。

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

使用委托的新实例取消注册事件


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

值得注意的是,不能保证 lambda 表达式形式的事件处理程序基于实例和方法签名强制执行唯一性。如果您需要取消订阅匿名方法,则需要将其提升为方法或保留对匿名方法的引用以供以后使用:

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

myEvent += meth;
myEvent -= meth;

Jon Skeet 详细回答了这个问题,并且可能比我做得更好:-)

如何删除 lambda 事件处理程序


轻微的重构

我将重构为以下内容:

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

    public override void Dispose()
    {
        SheetEvents.ButtonClick -= OnButtonClick;
        base.Dispose();
    }
}
于 2012-05-22T15:14:23.220 回答