私はデリゲートを保持するクラスを持っています。代議員のGC、何が欠けていますか? (私のデリゲートは収集されません)
私が評価したら、デリゲートを呼び出すことによって、デリゲートへの参照がクリアされ、コレクションの対象となることが期待されます。結局のところ、匿名メソッドとして構築されていれば、ローカル変数の世界を握っているかもしれません。
これを確認するために単体テストを構築しようとしましたが、私が計画した方法ではうまくいきませんでしたが、代わりにWeakReference
(ここではテスト目的で使用しました)他の仮定は、水を保持しません。
私はそれを想定したあなたはLINQPad
void Main()
{
WeakReference wr;
Lazy<int> l;
CreateTestData(out wr, out l);
wr.IsAlive.Dump(); // should be alive here
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
wr.IsAlive.Dump(); // and alive here as well
l.Value.Dump(); // but now we clear the reference
GC.Collect(); // so one of these should collect it
GC.WaitForPendingFinalizers();
GC.Collect();
wr.IsAlive.Dump(); // and then it should be gone here
GC.KeepAlive(l);
}
void CreateTestData(out WeakReference wr, out Lazy<int> l)
{
Func<int> f =() => 10;
wr = new WeakReference(f);
l = new Lazy<int>(f);
}
public class Lazy<T>
{
private Func<T> _GetValue;
private T _Value;
public Lazy(Func<T> getValue)
{
_GetValue = getValue;
}
public T Value
{
get
{
if (_GetValue != null)
{
_Value = _GetValue();
_GetValue = null;
}
return _Value;
}
}
}
で実行することができ、このコードを見てみましょう:
- かかわらず、デバッグビルドの、デバッガ添付、私は、デリゲートを作成したので、私が戻ってきた別のメソッドは、
WeakReference
とLazy<T>
オブジェクトを除く、デリゲートを保持するものは何もありません - 残された唯一の参照が
WeakReference
の1である場合と仮定し、
- につかまっそして、完全なガベージコレクションを強制される唯一の参照を減らすことになる、デリゲートへの参照を放棄する210オブジェクト
- はその後、デリゲートは、収集されるだろう、と私
WeakReference
は、オブジェクトがもはやコードの出力は、このように(コメント付き)であることが予想された
WeakReference
は
生きていることを示していないでしょう:
true // not gc'ed after construction
true // not gc'ed after full GC, still beind held by Lazy<T>
10 // value from calling delegate
false // but is now gc'ed, Lazy<T> no longer has a reference to it
しかし、その代わりに出力されます:
true
true
10
true
誰もが、私はここに欠けているものにいくつかの光を当てることができますか?
これは意味があります。デリゲートを変更して、結果を計算するためにローカル変数を使用しました。これは実際に収集されたものです。 –
サイド質問:私は、同じ型の複数のデリゲートが同じ定数値を返すことに気付くほどスマートではないと仮定しています。一度作成してどこでも再利用できますか? –
基本的に私の目標は、その特定のデリゲートが収集されたわけではなく、許可された場所でガベージコレクションを可能にするために、デリゲートへの参照が適切なタイミングで放棄されることを検証するテストを行うことでした。デリゲートを変更するだけで、その問題はわずかに解決され、テストは期待通りに実行されます。 –