5

イベントを持つモデルクラスがありSavedます。2 つのビューモデルがそのモデル オブジェクトを使用している場合、そのうちの 1 つがそれを変更すると、もう 1 つが更新されるという考え方です。

ビュー モデルを使用しなくなった場合、イベント ハンドラーを削除する必要がありますか? これが私のコードです:

protected AbstractEntityViewModel(AbstractEntity ae)
{
    this.ae = ae;

    ae.Saved += delegate(object o, EventArgs e) 
    { 
        base.OnPropertyChanged(null);
    };
}

-=これで問題ありませんか、ビューモデルが使用されなくなったときにデリゲートを削除できるように、これを変更する必要がありますか?

4

3 に答える 3

3

それの長短はイエスです。AbstractEntityオブジェクトへの参照がまだある場合、セカンダリオブジェクトを破棄することはできません。オブジェクトが破棄される可能性があり、イベントがまだ存在する場合(これは静的イベントにも当てはまります)、イベントハンドラーを手動で削除する必要があります。そうしないと、オブジェクトは破棄されません。

于 2012-04-16T16:00:27.370 に答える
2

イベントの方向性

本当にイベント ハンドラーをデタッチする必要があるかどうかを知るには、まず次のことを理解する必要があります。

ae.Saved += delegate(object o, EventArgs e) 
{ 
    base.OnPropertyChanged(null);
};

aeを参照していることを意味しますthis。したがって、イベントを持つオブジェクトは、イベント ハンドラーを持つオブジェクトを参照しています。その逆ではありません (イベント ハンドラーがイベントを参照する)。

GC ルートによって参照されていないオブジェクトを収集できます

さらに、ガベージ コレクションの対象となるオブジェクトが他のオブジェクトから参照されないことが理想的ですが、これは厳密には必要ではありません。

ガベージ コレクターは、GC ルート (パス) によって参照されていないすべてのオブジェクトを収集できます。これは、オブジェクトの孤立したグラフがある場合 (オブジェクトはグラフの他のオブジェクトを参照しているが、グラフ内のオブジェクトを参照しているオブジェクトがグラフの外にない [GC ルートもありません])、オブジェクト グラフ全体最終的にガベージコレクションされます。グラフが絡み合っているほど、GC がグラフを収集するためのコストが高くなります。イベント ハンドラーをデタッチすると、そのようなグラフをより迅速に解消するのに役立ちます。

オブジェクトを正しくクリーンアップする

.Net にはデストラクタがありません。代わりに、IDisposableパターンとファイナライザーがあります (「非管理リソースをクリーンアップするための Finalize と Dispose の実装」を参照)。

簡単に言えば:

  • オブジェクトがアンマネージ リソースを管理する場合は、ファイナライズ メソッド ( ~Foo () { }for ) が必要です。class Fooこれらは、GC がオブジェクトを収集しているときに、ガベージ コレクターによって呼び出されます。したがって、正確な瞬間はあなた次第ではありません。
  • 使い捨てパターンを使用して、マネージド リソースとアンマネージド リソースをクリーンアップできます。オブジェクトに管理されていないリソースがある場合でも、ファイナライザーが必要です。なんで?Dispose()メソッドはあなたによって呼び出されます。実行されているという保証はありません。アプリケーションがDispose()メソッドの呼び出しに失敗した場合でも、finalize を呼び出す GC が存在します。したがって、基本的に Dispose で管理されていないリソースのクリーンアップを行うことは、パフォーマンスの向上にすぎません (状況によっては、コンピューターに数ギガバイトの RAM を追加したい場合を除き、これは非常に重要になる場合があります...)。

ファイナライザーを使用する予定がある場合は、ドキュメントを読むことを強くお勧めします。ここで取り上げていないことがかなりあるからです。アンマネージ リソースをクリーンアップするための Finalize と Dispose の実装を参照してください。

あなたの例

あなたの例に戻ると、 a を構築した後、 に渡したがAbstractEntityViewModel生きている限り、それは生き続けます。しかし、これら 2 つのどちらも GC ルートによって参照されていない場合、両方ともガベージ コレクションされます。AbstractEntityAbstractEntityViewModel

イベント ハンドラーを切り離すと、ガベージ コレクションができAbstractEntityViewModelなくても (具体的なサブクラス インスタンス) をガベージ コレクションできますAbstractEntity

参照: .NET でのガベージ コレクションについて


于 2014-10-17T12:23:13.907 に答える
1

イベントは、基本的なオブザーバーの実装であると考えることができます。サブジェクトは、サブスクライブされたすべてのオブザーバーへのハンドラーを保持します。つまり、それらはガベージ コレクションされません。オブザーバーをガベージ コレクションできるようにするには、サブジェクトからオブザーバーとして削除する必要があります。

イベント ハンドラーを手動で削除する必要がないのは、サブジェクトとオブザーバーが同じインスタンスである場合のみです。これは、ガベージ コレクターが循環参照を検出し、その後オブジェクトをファイナライズするためです。

于 2012-04-16T16:28:03.387 に答える