动态对象的垃圾收集

时间:2011-12-19 06:10:21

标签: c# garbage-collection

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;
}

现在会发生什么?

5 个答案:

答案 0 :(得分:4)

从不“标记为垃圾收集”......它是一个对象并存在 - 足以让GC考虑它。分配到字段和变量只会影响成功收集。

关于第二个例子:

  • 如果它在堆栈中作为值(从xyz()返回),则不会被收集
  • 如果它保存在局部变量中,则不会被收集(可能取决于该变量是否再次读取,具体取决于GC实现)
  • 如果它作为可到达(不可收集)对象上的字段保存在某处,则不会被收集

答案 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,如图所示

enter image description here

当您设置a = null;时,您只是删除对堆上对象Foo的引用,并且不再引用它。

GC将收集不再引用的任何此类对象。

在方法内创建对象并从方法返回时也一样 返回时,您在方法中创建的引用(如a)将从堆栈中清除,并且不再引用您在方法内创建的对象(除非返回引用)。 GC收集它。