イベントの方向性
本当にイベント ハンドラーをデタッチする必要があるかどうかを知るには、まず次のことを理解する必要があります。
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 ルートによって参照されていない場合、両方ともガベージ コレクションされます。AbstractEntity
AbstractEntityViewModel
イベント ハンドラーを切り離すと、ガベージ コレクションができAbstractEntityViewModel
なくても (具体的なサブクラス インスタンス) をガベージ コレクションできますAbstractEntity
。
参照: .NET でのガベージ コレクションについて