这个事件处理程序代码会导致内存泄漏吗?

时间:2012-11-14 03:15:49

标签: c# .net wpf

假设我派生了一个WPF控件,例如TextBox,我覆盖其中一个On-方法,例如OnInitialized

假设我这样做了:this.Initialized += delegate { };

如果包含此控件的窗口关闭 - 如果没有其他操作,这会导致内存泄漏吗?

如果这确实导致内存泄漏,那么实现Finalizer是否是一个足够的,最小的补救措施?

1 个答案:

答案 0 :(得分:5)

我相信您正在考虑的内存泄漏是将事件处理程序附加到对象上的事件(称为“A”),然后丢失对拥有该处理程序的对象(“B”)的所有引用。垃圾收集器仍然可以通过对象“A”事件到达对象“B”,因此永远不会收集它。有关更多讨论,请参阅this question

在您的情况下,您正在Form内附加处理程序。关闭Form并删除对它的所有引用后,无法从其余代码中获取表单,以便GC愉快地收集它(当它到达它时)。不会发生泄漏。

根据您的上一条评论,实施终结器可能无法完成您的想法。它只是运行时为您提供执行某些清理代码的钩子,您最好实现IDisposable interface and pattern。我倾向于在暴露事件的类中做的一件事是在Dispose方法中将事件设置为null。即:

class Foo : IDisposable
{
    public event EventHandler SomethingHappened;

    // ... normal IDisposable implementation details left out

    protected virtual void Dispose(bool Disposing)
    {
        if (Disposing)
        {
            SomethingHappened = null;
        }
    }
}

我不是在所有的类中都这样做,但它是一种相对干净的方法,可以在对象消失时从对象中删除所有处理程序。你只能从课堂内部做到这一点。

在任何情况下,如果您要根据Form事件在PreviewMouseLeftButtonDown中工作,则应改为覆盖OnPreviewMouseLeftButtonDown方法。附加事件处理程序来监听类自己的事件通常是不好的形式。请改为:

protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e)
{
    // Actually raise the event to let other classes know it happened
    base.OnPreviewMouseLeftButtonDown(e);

    // your code...
}