垃圾收集环境中对象的生命周期

时间:2014-01-13 21:05:40

标签: c# garbage-collection lifecycle

我的问题很简单,专门针对带有CLR的C#。

首先我们得到了代码片段1:

public void f(SomeClass sc)
{
   anExistingInstance.FieldOfSomeClass = sc;
}

现在是代码段2:

public void f()
{
  SomeClass sc = new SomeClass();
  anExisitingInstance.FieldOfSomeClass = sc;
}

在代码1中,当调用f并定义sc的方法结束时,我猜测sc已被释放,这就是anExisitingInstance.FieldOfSomeClass不再存在的原因有效的。

我的问题是为什么在代码2中不会发生同样的事情,而是使用方法f本身?为什么在f完成后,anExisitingInstance.FieldOfSomeClass仍然保持正确的值?

4 个答案:

答案 0 :(得分:2)

您示例中唯一重要的实体是anExistingInstance。我们不知道它的定义位置以及谁拥有对它的引用,但是此对象包含对SomeClass实例的引用。 创建 SomeClass实例的人并不重要,只是anExistingInstance拥有对它的引用。其他一些类可能会引用anExistingInstane,依此类推,直到你到达GC根目录。

只要您的SomeClass实例链接回GC根目录,就不会进行垃圾回收。一旦此链中的任何链接不再链接到GC根(比方说,有人发布了对anExistingInstance的引用,它引用的所有对象(未被其他东西引用)都有资格进行垃圾回收

答案 1 :(得分:1)

  

在代码1中,当调用f和定义的sc的方法结束时,我猜测sc被释放了,这就是为什么anExisitingInstance.FieldOfSomeClass不再有效。

没有。当anExistingInstance超出范围时,则其所有字段也不再可访问(除非另一个对象引用)。因此,sc仅在anExistingInstance不在范围内时才有资格进行垃圾回收。

如果在父级/生根对象仍然在范围内时收集了对象,则代码中会抛出10000多倍NullReferenceException

  

我的问题是为什么在代码2中不会发生同样的事情,而是使用方法f本身?为什么当f完成时,anExisitingInstance.FieldOfSomeClass仍然保持正确的值?

它是一样的。即使在该方法中创建了sc,它现在也以anExistingInstance对象为根。一旦anExistingInstance超出范围,sc也有资格进行垃圾收集。

答案 2 :(得分:0)

  

我的问题是为什么在代码2中不会发生同样的事情,而是使用方法f本身?

因为包含方法f的类尚未处理。请参阅第一种情况,其他人创建sc以便它能够处置它 - 但在第二种情况下,您在方法中创建了sc。它将保留在范围内,而创建它的类在范围内。

答案 3 :(得分:0)

Why when f is done, anExisitingInstance.FieldOfSomeClass still holds a correct value?

当没有对它的引用时,对象被垃圾收集。在这两种情况下,都有一个对象anExisitingInstance,其中包含对SomeClass的引用。并且在anExisitingInstance gc'es时会被gc'ed。