私のソフトウェアに2つのオブジェクトインスタンスがあり、そのうちの1つがもう1つのオブジェクトインスタンスにサブスクライブされている場合。ガベージコレクタによって浄化されるために孤児になる前に、それらを互いに解約する必要がありますか?または、私がイベントの関係をクリアする理由が他にありますか?オブジェクトのサブスクライブが孤立していても、サブスクライバが孤立している場合、またはその逆の場合はどうなりますか?オブジェクトが孤立する前にオブジェクトからイベントサブスクリプションを削除する必要はありますか?
答えて
はい、あります。イベントの発行者はオブジェクトへの参照を保持していて、ガベージコレクションされないようにします。
例を見て、どうなるか見てみましょう。私たちには2つのクラスがあります。一方が他方がそれを消費し、イベントを公開します。ClassBのはにClassAのインスタンスへの参照を格納していませんか
class ClassA
{
public event EventHandler Test;
~ClassA()
{
Console.WriteLine("A being collected");
}
}
class ClassB
{
public ClassB(ClassA instance)
{
instance.Test += new EventHandler(instance_Test);
}
~ClassB()
{
Console.WriteLine("B being collected");
}
void instance_Test(object sender, EventArgs e)
{
// this space is intentionally left blank
}
}
注意。単にイベントハンドラをフックアップするだけです。
ここでオブジェクトの収集方法を見てみましょう。シナリオ1:
ClassB temp = new ClassB(new ClassA());
Console.WriteLine("Collect 1");
GC.Collect();
Console.ReadKey();
temp = null;
Console.WriteLine("Collect 2");
GC.Collect();
Console.ReadKey();
クラスBインスタンスを作成し、temp変数を使用してそのインスタンスへの参照を保持します。 ClassAの新しいインスタンスが渡されます。そこにはどこにも参照が格納されないため、ClassBコンストラクタが完了した直後にスコープから外れます。 ClassAがスコープから外れたときと、ClassBがスコープから外れたときに一度実行されるガベージコレクタがあります。出力:
Collect 1
A being collected
Collect 2
B being collected
シナリオ2:
ClassA temp = new ClassA();
ClassB temp2 = new ClassB(temp);
temp2 = null;
Console.WriteLine("Collect 1");
GC.Collect();
Console.ReadKey();
temp = null;
Console.WriteLine("Collect 2");
GC.Collect();
Console.ReadKey();
ClassAクラスの新しいインスタンスが作成され、それへの参照を一時変数に格納されています。 ClassBの新しいインスタンスが作成され、tempのClassAインスタンスが渡され、temp2にそのインスタンスへの参照が格納されます。次に、temp2をnullに設定して、ClassBインスタンスをスコープから外します。前述のように、各インスタンスがスコープ外になったらガベージコレクタを実行します。出力:
Collect 1
Collect 2
B being collected
A being collected
したがって、イベントを公開するインスタンスがスコープ外になると、イベントハンドラがフックアップされているかどうかにかかわらず、ガベージコレクションのために利用可能になります。イベントハンドラを持つインスタンスが別のインスタンスのイベントにフックアップされた場合、イベントハンドラがデタッチされるか、またはイベントハンドラがアタッチされるインスタンスがガベージコレクションに使用可能になるまで、ガベージコレクションに使用できなくなります。
はあなただけイベントを暴露オブジェクトは、長寿命である場合、イベントを外しする必要がありますが、オブジェクトは、イベントがそうでなければ短命だろうをフック(ゴミはかなり迅速に収集されます)。
この場合、アンリックに失敗すると、短命オブジェクトがGCできなくなるため、メモリリークが発生します。これは、長期保存オブジェクトのイベントがデリゲートに保持されるためです。短命オブジェクトへの参照を保持します。短命のオブジェクトは依然としてそのデリゲートによって参照されているので、ガベージコレクションされません。
静的イベントは、定義によって長く存続します。これらのイベントは、プログラムが終了するまで存続します。静的イベントをフックすると、完了したら間違いなくアンフックする必要があります。
両方のオブジェクトが孤立しようとしている場合は、アンフックは必要ありません。
イベントを購読すると、サブスクライバへの参照が強くなります。これは、表の下でイベントが代理人であり、インスタンスメソッドへの代理人がオブジェクト参照と実際のメソッドの組み合わせであるためです。登録を解除しないと、サイト運営者は引き続き参照を維持し、サイト運営者が生存している限り、登録しているオブジェクトは本当に孤立した状態になることはありません(GC'ed)。
逆のことは当てはまりません。つまり、サブスクライブされたオブジェクトにはパブリッシャへの参照がありません。
- 1. 新しいオブジェクトを挿入する前にリストからオブジェクトを削除する必要がありますか?
- 2. 処分する前にコントロールが親オブジェクトから適切に削除する必要がありますか?
- 3. RestKitローカルストアから孤立したオブジェクトを削除しない
- 4. RestKit孤立したオブジェクトの削除ルール
- 5. Entity Framework削除時に孤立したオブジェクトを残す
- 6. すぐに孤立したオブジェクトのRestkitと削除3
- 7. javascriptオブジェクトからオブジェクト名を "削除"する方法はありますか?
- 8. gcnewに割り当てられたオブジェクトでは、いつ削除する必要がありますか?
- 9. ウェブサイトからプリローダーを削除する必要があります
- 10. CameraCaptureUIからStorageFileを削除する必要があります
- 11. カスタムフォーマットのオブジェクトをクリップボードから明示的に削除する必要がありますか?
- 12. IVYリポジトリから孤立したJARを削除する
- 13. オブジェクトを削除するためにオブジェクトを拡張する必要があるのはなぜですか?
- 14. パラメータを渡すときに作成されるオブジェクトは削除する必要がありますか?
- 15. AS3:addChildの前にChildを削除する必要がありますか?
- 16. dismissModalViewControllerAnimatedはスーパービューから削除する前に最初にアニメーション化する必要がありますか?
- 17. NHibernate Exception:孤立した削除のコレクションスナップショットがありません
- 18. 私はUITouchオブジェクトをリリースする必要がありますか?
- 19. オブジェクトをNotificationCenterに送信する前にオブジェクトを自動リリースする必要がありますか?
- 20. Cocoaでは、オブジェクトの割り当てを解除するときに、KVO通知を受け取るオブジェクトを削除する必要がありますか?
- 21. 静的ベクトルは削除する必要がありますか?
- 22. 要素を削除する前にjqueryイベントのバインドを解除する必要がありますか?
- 23. コールバックを持つ別のオブジェクトが所有するオブジェクトを、削除するオブジェクトから削除できますか?
- 24. オブジェクトを-performSelector:withObject:afterDelay:に渡す前にオブジェクトを保持する必要がありますか
- 25. テーブルから孤児を削除する
- 26. イベントハンドラを削除する必要がありますか?
- 27. Elasticsearchエイリアスを削除する必要がありますか?
- 28. 仮想インデックスを削除する必要がありますか?
- 29. OOP - 投稿を削除する必要がありますか?
- 30. System.Windows.Media.Penを削除する必要がありますか?