8
我有一個課程,堅持一個代表,以便稍後懶洋洋地評價一些東西。代表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;
}
}
}
運行我假設:
- 不管DEBUG編譯器,調試器的連接,因爲我在創建委託單獨的方法,我從哪裏回來,除了
WeakReference
和Lazy<T>
對象 - 如果我要求
Lazy<T>
對象放棄其參考代表,這將減少到只有一個WeakReference
是堅持以 - 的引用,然後強制完整垃圾回收,假設如果只參考左邊是一個在
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
任何人都可以揭示什麼我失蹤這裏一些輕?
好的,這是有道理的。我改變了委託,以便它使用一個局部變量來計算它的結果,而這確實是收集的。 –
副題:我假設編譯器不夠聰明,無法注意到同一類型的多個委託返回相同的常量值,可以創建一次並隨處重複使用? –
基本上,我的目標是進行測試,驗證在正確的時間放棄了對委託的引用,以便在允許的情況下進行垃圾回收,而不一定要收集該特定的代表。改變委託只是稍微解決了這個問題,測試現在按預期運行。 –