2016-09-06 68 views
0

假設我有這樣的代碼:在c#中如何知道一個弱引用的對象是否會被垃圾收集?

class Test 
{ 
    WeakReference m_ref; 

    public Test() 
    { 
     Test1(); 
     Test2(); 
    } 

    void Test1() 
    { 
     m_ref = new WeakReference(new object()); 
    } 

    void Test2() 
    { 
     // If I do the GC then the m_ref.Target is null 
     // GC.Collect(); 
     Debug.Log(m_ref.Target); 
    } 
} 

void TestFunc() 
{ 
    new Test(); 
} 

在這個例子中我創建了一個新的對象實例,並將其設置爲WeakReference例如在Test1。如果我在退出Test1後正確理解,那麼對象實例將沒有任何引用,因此此實例即將爲GC

但是,在Test2如果GC未執行,我仍然可以通過m_ref.Target訪問對象實例。

有沒有什麼辦法,我可以知道m_ref.Target無效沒有手動執行GC

+0

你試過'm_ref.IsAlive'? – hellowstone

+0

@hellowstone我試過了。如果我不打電話給GC,它會返回'true'。看起來它與'Target!= null'等價嗎? – jayatubi

+0

難道你不需要一個強大的參考,直到你不需要它,然後使它變弱? – Sinatr

回答

3

不,你不能。按照設計,WeakReference與垃圾收集器緊密耦合。即使是documentation提到它:

獲取指示當前的WeakReference對象引用的對象是否已被垃圾回收。

據我所知,有一個在C#沒有辦法知道是否仍有給定對象活着引用,也許除了手動瀏覽整個參考樹(和幾乎重新實現GC自己)。

+0

所以目前我只能知道對象**已被**收集,但我無法知道它**要收集**嗎? – jayatubi

+0

@jayatubi是。 GC本身並不知道它在實際運行之前會收集哪些對象 –

2

有沒有什麼辦法可以知道m_ref.Target無效而無需手動執行GC?

它是而不是直到GC收集對象爲止無效。垃圾收集的關鍵是你不知道,而且你不必關心該對象何時被丟棄。

在你的例子中,是的,你是對的,m_ref = new WeakReference(new object());執行後,實例將被收集'很快'。然而,'很快'沒有具體定義,所以你不能認爲這會在調用Test2和執行Debug.Log(m_ref.Target);之前發生。

+0

有沒有辦法檢查當前C#版本中WeakReference.Target的引用計數? – jayatubi

+3

@jayatubi不,因爲GC不使用引用計數,所以不太可能存在每個引用計數,它從它的根對象執行遞歸掃描並收集不在掃描中的東西。 –

+0

@ScottChamberlain所以這意味着即使實例處於'孤立'狀態,但是在GC開始掃描之前,沒有人知道這一點? – jayatubi

0

如果我退出的Test1就什麼也沒有參考對象實例後,正確地理解......

你錯了。從技術上講,你沒有任何創建對象的引用,它可以可能 gc'ed在下一行。

考慮一個簡單的例子:

class Program 
{ 
    static WeakReference _ref; 

    static void Main(string[] args) 
    { 
     Test(); 
     GC.Collect(); 
     Console.WriteLine(_ref.IsAlive); // false 
    } 

    static void Test() 
    { 
     var obj = new object(); 
     _ref = new WeakReference(obj); 
     GC.Collect(); 
     Console.WriteLine(_ref.IsAlive); // true 
    } 
} 

Test()我們有強大的參考對象,它的確持續到方法的結束。

你可以做這樣的事情,以確保

object obj = _ref.Target; 
if (obj != null) 
{ 
    ... safe to do something with obj 
} 
+0

在我的特殊情況下,即使它活着,obj也不安全。因爲我的案例obj確實是一個代表。委託的上下文可能不再有效,所以即使委託本身僅有效,我也無法調用它。 – jayatubi

相關問題