Foo a;
try
{
// some work with a;
}
finally
{
a = null;
}
在这个例子中,我们将对象a标记为垃圾收集。
现在假设,我们修改这样的代码。
public xyz()
{
return new Foo();
}
现在在这个例子中,新创建的对象没有名称,所以何时将其标记为集合?或者GC会自动确定它没用,所以它会尝试恢复它吗?
编辑:
在阅读完答案后,我又补充了一个情况。
Foo a;
try
{
return a;
}
finally
{
a = null;
}
现在会发生什么?
答案 0 :(得分:4)
从不“标记为垃圾收集”......它是一个对象并存在 - 足以让GC考虑它。分配到字段和变量只会影响成功收集。
关于第二个例子:
xyz()
返回),则不会被收集答案 1 :(得分:2)
如果xyz的调用者将结果分配给某个东西,那么它会一直存在,否则它最终会被GC化。只需要一些东西来保持对象的参考,以便在GC中生存。
答案 2 :(得分:2)
在这个例子中,我们将对象a标记为垃圾收集。
不,你没有。除非您稍后在代码中使用该变量,否则垃圾收集器已经知道该引用不再被使用。它可以在最后一次使用后收集对象,因此甚至可以在之前收集对象将引用设置为null。
就垃圾收集器而言,将引用设置为null根本不起作用,除非您稍后在代码中使用该变量。
Foo a = new A();
try {
// some work with a;
// at this point a is no longer used, so it can be collected
} finally {
// this has no effect on garbage collection:
a = null;
}
您根本不需要对物体做任何事情以使它们具有收藏价值,您只需停止使用它们,它们就会被收集。
需要特殊处理的唯一对象是实现IDisposable
接口的对象。完成后,您应该对这些对象调用Dispose
方法,或者将它们放在using
块中,这将自动调用Dispose
。
在添加的方案中,您将变量设置为null,这对垃圾回收也没有影响。您将局部变量设置为null,这对您已经移交的对象引用没有影响。
答案 3 :(得分:1)
这是关于C#Object Lifetime的一个有趣的article in MSDN。
摘录:
垃圾收集器跟踪对象引用并标识对象 通过运行代码无法再访问
它明确表示它不使用引用计数,而是扫描对象是否具有任何可访问引用的替代方法。如果代码无法访问对象,则会将其标记为要收集。
答案 4 :(得分:0)
当您编写Foo a;
时,您只创建一个内存来引用堆栈上类型为Foo
的对象。
当您编写new Foo();
时,您只在堆上创建类型为Foo
的对象而没有引用。
当您撰写Foo a = new Foo();
时,您正在a
在堆上引用对象Foo
,如图所示
当您设置a = null;
时,您只是删除对堆上对象Foo
的引用,并且不再引用它。
GC将收集不再引用的任何此类对象。
在方法内创建对象并从方法返回时也一样
返回时,您在方法中创建的引用(如a
)将从堆栈中清除,并且不再引用您在方法内创建的对象(除非返回引用)。 GC收集它。