垃圾收集器会收集由c#代码创建的对象吗?

本文关键字:创建 代码 对象 收集器 | 更新日期: 2023-09-27 18:10:18

我有以下代码:

public abstract class State
{
    public abstract void HandleState();
}
public class StateA : State
{
    public override void HandleState()
    {
       // do stuff here
       ....
       // this returns a new state object, and there are multiple, like StateB, StateC etc.
       State newState = GetNewState(); 
       newState.HandleState();
    }
}

假设状态对象一直被无限返回,垃圾收集器是否能够收集由这段代码生成的对象?

垃圾收集器会收集由c#代码创建的对象吗?

嗯,这取决于GetNewState返回什么。如果您通过创建StateA的新实例来创建堆栈溢出(正如fracimadric Hamidi指出的那样),那么您将获得StackOverflowException(很可能在GC尝试运行之前)。

然而,如果GetNewState()返回的是另一个对象的实例,而没有创建反过来递归创建新State对象的对象,那么它们最终将在不再引用后的某个时刻被垃圾收集(垃圾收集是不确定的,当它到达时将清理未使用的内存)。

不会导致堆栈溢出的实现示例:

public class StateB : State
{
   public override void HandleState()
   {
     // do stuff here - that doesn't keep creating new State objects.
     ....
   }
}

正如Eugene Podskal所指出的,那些被创建的类可以创建对它们自己的引用,从而使它们不被垃圾收集。如:

public class StateC : State
{
   private static List<StateC> _myStates = new List<StateC>();
   public StateC()
   {
       //Unless items are removed at some point from _myStates, they 
       // won't get garbage collected.
       _myStates.Add(this);
   }
   public override void HandleState()
   {
     // do stuff here
   }
}

No。您保留了对堆栈中这些旧的State对象的所有引用,您不断地向下挖掘,而(显然)永远不会从堆栈中返回。由于您保留了对旧状态对象的引用,因此它们不会被GCed。

一旦(if)你到达任何点,你不生成一个新的状态和"回到堆栈",那么对象将能够被回收