6

TextBox などの WPF コントロールを派生させ、OnInitialized などの On- メソッドの 1 つをオーバーライドするとします。

私がこれをしたとします:this.Initialized += delegate { };

このコントロールを含むウィンドウが閉じられた場合 - 他に何もしないとメモリ リークが発生しますか?

これによりメモリ リークが発生する場合、Finalizer を実装するだけで十分で最小限の解決策になりますか?

4

1 に答える 1

5

あなたが考えているメモリリークは、イベントハンドラーをオブジェクトのイベントにアタッチし(「A」と呼びます)、ハンドラーを所有するオブジェクト(「B」)へのすべての参照を失うことです。ガベージ コレクタは、オブジェクト「A」のイベントを通じてオブジェクト「B」に到達できるため、オブジェクトを収集することはありません。詳細については、この質問を参照してください。

あなたの場合、Form. がForm閉じられ、それへのすべての参照を削除すると、コードの残りの部分からフォームにアクセスする方法がないため、GC は喜んでそれを収集します (フォームに到達したとき)。漏れは発生しません。

最後のコメントに基づいて、ファイナライザーの実装は、あなたが思っていることをしないかもしれません。これは、クリーンアップ コードを実行するためにランタイムが提供する単なるフックであり、IDisposable interface と patternを実装することをお勧めします。イベントを公開するクラスでよく行うことの 1 つは、メソッドでイベントを null に設定するDisposeことです。すなわち:

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 に答える