GC.Collect() seemingly doesn't actually collect an object

The following always logs true:

public class Tests : MonoBehaviour
{

  void Start()
  {
    var obj = new System.Object();
    var weakRef = new System.WeakReference(obj);

    obj = null;

    GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, blocking: true);
    GC.WaitForPendingFinalizers();

    Debug.Log(weakRef.IsAlive);
  }

}

Whereas an equivalent code compiled outside Unity always logs false:

class Program
{
    static void Main(string[] args)
    {
        var obj = new System.Object();
        var weakRef = new System.WeakReference(obj);

        obj = null;

        GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, blocking: true);
        GC.WaitForPendingFinalizers();

        Console.WriteLine(weakRef.IsAlive.ToString());
        Console.ReadKey();
    }
}

Is this intentional? If it is, is there any way in Unity to ensure that an object to which there are no (strong) references is collected before end of the current scope?

GC in C# is a generic issue - not Unity specific.

There is no reasonable way of relying 100% on an object’s memory destruction (collection) at any given point in time. As such RAII (a useful technique in C++) is not directly possible in C#; for further info on that, here is an answer in Stack Overflow discussing it.

For more understanding of GC, refer to the Microsoft documentation guide.

1 Like