6

假设我派生了一个 WPF 控件,例如 TextBox,并且我重写了其中一个 On- 方法,例如 OnInitialized

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

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

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

4

1 回答 1

5

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

在您的情况下,您从Form. 当Form关闭并删除对它的所有引用时,无法从其余代码中获取表单,因此 GC 会愉快地收集它(当它找到它时)。不会发生泄漏。

根据您最后的评论,实现终结器可能不会像您认为的那样。这只是运行时提供给您执行一些清理代码的钩子,您最好实现IDisposable interface 和 pattern。我倾向于在暴露事件的类中做的一件事是在Dispose方法中将事件设置为 null。IE:

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...
}
于 2012-11-14T03:40:55.410 回答