日期:2014-05-17  浏览次数:21111 次

关于.NET垃圾资源回收的三个小问题,请各位前辈帮忙(谢谢)
请教各位前辈以下三个问题,谢谢帮忙分析:)


class A
{
public int Get()
{
//方法Get代码(略)
}
    //类A其他代码(略)
}

class B
{
    public A GetA()
    {
        A a = new A();
        return a;
    }
}

class C
{
    private A _a = null;
    
    public void Exec()
    {
        B b = new B;
        this._a = b.GetA();
        b = null; //问题1:请教这里运行完毕后,_a的值会安全么(会不会由于b=null,_a(保存的类A的实例引用)被.NET垃圾回收期回收到呀?)
                  //问题2:b=null的意思是不是就是告诉.NET可以对其进行垃圾回收处理呀?
    }
    
    public void Run()
    {
     int i =this._a.Get(); //问题3:请教这个方法里或类C的其他方法中使用_a(保存的是类A的实例引用)会安全么?
    }
}


------解决方案--------------------
我的理解:
问题1:_a与b没有什么联系,b.GetA()的时候,会在堆上创建新的引用给_a使用。b = null对_a没有影响
问题2:b = null之后,b相当于没有任何引用,肯定会被GC回收掉。但是什么时候回收就不知道了
问题3:如果_a = null,会报异常null reference...
------解决方案--------------------
1.b实例是不会在离开当前方法前被回收掉,也就是不可能为null
2.只是指明堆中的B对象实例没有被任何地方引用,可以被回收,但什么时候回收只有上帝知道了
3.不明白什么意思

PS,上面2楼所说的有疵漏,要看他对这个安全的定义到底是什么。如果是指你不需要显示去管理回收资源的话这个就存在问题,比如事件委托这块在一些情况下会导致无法回收(可以使用WeakReference或显示去除事件对应的挂接解决)
再比如在显示指定某个对象中每个字段的FieldOffSet时如果不加以注意也可能会导致一些非意料后果,比如绕开编译器保证修改readonly字段等
------解决方案--------------------
引用:
1.b实例是不会在离开当前方法前被回收掉,也就是不可能为null
2.只是指明堆中的B对象实例没有被任何地方引用,可以被回收,但什么时候回收只有上帝知道了
3.不明白什么意思

PS,上面2楼所说的有疵漏,要看他对这个安全的定义到底是什么。如果是指你不需要显示去管理回收资源的话这个就存在问题,比如事件委托这块在一些情况下会导致无法回收(可以使用WeakRefere……

1说错了,没看到最后面你将b设为空这句话。你a对象不会为空

------解决方案--------------------
引用:
引用:引用:引用:1.b实例是不会在离开当前方法前被回收掉,也就是不可能为null
2.只是指明堆中的B对象实例没有被任何地方引用,可以被回收,但什么时候回收只有上帝知道了
3.不明白什么意思

“A a = new A();”是在B类中声明的,在C……

可以这么理解,但略有不同,我的理解是这样的。
但是GC 都是从 对象根开始 找起,先归类,把 有引用的提出来,添加到 一个空间假设G中。
比如上面的例子
1. 假设 GC先 遍历b,b=null,这时,b及b下的所有对象都不会添加到 G,不会再遍历b的内部了,
2. b遍历完,假设 轮到 C,c有引用,c添加到G区,再遍历c下的对象,又遍历到a了,a再添加到G区,依次类推,没有添加进来的都是垃圾对象,将释放。