我需要取消所有事件处理程序吗?

10

在VS中的设计器中,例如你双击一个按钮,它会生成这个Click事件处理程序。

订阅代码在designer.cs文件中。

我想知道,在dispose方法中,我是否必须取消事件的订阅?

此外,所有在窗体中的控件在窗体dispose时都会被销毁吗?它实际上会递归地对每个控件调用dispose吗?

3个回答

15

如果您只是挂接自己的事件,就不需要在Dispose方法中取消事件挂接。

只有当您要挂接另一个对象的事件时才需要考虑这个问题。因为事件挂接会使订阅者保持引用,如果没有取消挂接,那么只要可观察对象还存在,您就无法进行垃圾回收。

当您挂接自己的事件时,您拥有对自身的引用,形成了循环引用,因此您不必担心这个问题。

出于这个原因,我支持更松散耦合的事件模式。这是.Net中最容易产生内存泄漏的地方。我更喜欢使用事件聚合器模式(具有弱事件)。


感谢您的精彩解释。当您将自己连接到钩子时,不解除连接是完全有道理的。 - pdiddy

2

关于“它是否会递归地调用每个控件的dispose方法?”这个问题,答案是肯定的。

可以通过在控件的Dispose方法中设置断点来进行简单测试。

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        this.Controls.Add(new SuperButton());
    }
}

public class SuperButton : Button
{
    protected override void Dispose(bool disposing)
    {
        //Place breakpoint on the line below
        base.Dispose(disposing); 
    }
}

1
只要事件处理程序代码是表单本身,那么您就不需要取消订阅事件 - 因为随着表单本身的销毁,控件上就不会有悬挂的事件处理程序。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接