保持对象作为成员的引用会阻止收集吗?

时间:2016-05-18 14:19:00

标签: c# .net garbage-collection

考虑以下代码,其中A类负责管理本机数据。指向该数据的指针被传递给B类,因此我需要在使用B时不收集A:

class A
{
    public A(string n)
    {
        _n = n;
        _p = IntPtr.Zero; //acquire native resource
    }

    public IntPtr GetP()
    {
        return _p;
    }

    ~A()
    {
        Console.WriteLine("Free native resource {0}", _n);
    }

    string _n;
    IntPtr _p;
};

class B
{
    public B(IntPtr p)
    {
        _p = p;
    }

    public B(IntPtr p, Object o)
    {
        _p = p;
        _o = o;
    }

    public IntPtr GetP()
    {
        return _p;
    }

    IntPtr _p;
    Object _o;
};

如果我没有从'b'中引用'a','a'会立即按预期收集,这会留下指向无效数据的指针(至少在visual studio中,单声道中的gc是不那么急切:

static void Main(string[] args)
{
    var a = new A("a");
    var b = new B(a.GetP());
    GC.Collect();
    GC.WaitForPendingFinalizers();
    Console.WriteLine("b._p: {0}", b.GetP());
}

Output:
Free native resource a
b._p: 0

但如果我从'b'中引用'a',那么'a'在退出之前不会被释放,即使以后没有使用'a':

static void Main(string[] args)
{
    var a = new A("a");
    var b = new B(a.GetP(), a);
    GC.Collect();
    GC.WaitForPendingFinalizers();
    Console.WriteLine("b._p: {0}", b.GetP());
}

Output:
b._p: 0
Free native resource a

所以我的问题是:在第二种情况下,'a'保证规则是活着的,而'b'没有被收集,或者这种行为依赖于实现?如果是后者,我将如何保持活着?我见过几个类似的问题,但我没有找到明确的答案。

1 个答案:

答案 0 :(得分:5)

  

所以我的问题是:在第二种情况下,'a'保证规格是活着的,而'b'没有被收集,

是。如果b引用了a且未收集,则也不会收集a