2016-09-06 97 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

相关问题