Freigeben über


A good reason for calling GC.Collect()

You've probably heard that you should not call GC.Collect() and generally speaking this is absolutely correct. Yes, there are probably exceptions to that rule but unless you know for sure that calling GC.Collect() will improve the runtime behavior of your application you should refrain from making that call. Also, let's not forget that implementation details of the garbage collector can change between releases of the CLR. However, the possibility of forcing a garbage collection can come in very handy for testing or debugging purposes. Let's consider the following static class:

public static class MyClass

{

    private static Collection<object> objects = new Collection<object>();

    public static void RegisterObject(object o)

    {

        objects.Add(o);

   }

    public static void ReleaseAllObjects()

    {

        objects.Clear();

    }

}

This class is of course pretty pointless. But it is suitable for illustrating a scenario in which a class holds references to an object created by a caller thus influencing the lifetime of that object. Instead of a ReleaseAllObjects() method you could for example think of a class that releases references when certain events occur. Either way, you might want to write a test which actually verifies that all object references have been deleted at a certain point. This is a problem GC.Collect() helps us to solve as an object without any references to it is automatically destructed by the garbage collector and because of the nondeterministic nature of the collector we have to manually trigger a collection. So, a step-by-step description of the test looks like this:

  1. Create an object
  2. Pass a reference to the MyClass class by calling RegisterObject(object)
  3. Delete the local reference on the caller side
  4. Call MyClass.ReleaseAllObjects()
  5. Call GC.Collect()
  6. Verify that the object has been destructed

Obviously we are still missing an important piece that allows us to do the actual verification that the object is no more. And that piece is a weak reference. Automated tests checking the lifetime of objects aside, weak references allow an object to keep a reference to another object without keeping the garbage collector from collection it (in other words, the garbage collector will ignore all weak references when determining if an object is still referenced or not). By creating a WeakReference referencing the object before deleting the regular reference to it we can verify that it has been collected by checking the IsAlive property which must be false at the end of the test:

[TestClass]

public class MyClassTests

{

    [TestMethod]

    public void ObjectLifetimeTest()

    {

        object someObject = new object();

        WeakReference weakObjectReference = new WeakReference(someObject);

        MyClass.RegisterObject(someObject);

        someObject = null;

       

        MyClass.ReleaseAllObjects();

        GC.Collect();

        Assert.IsFalse(weakObjectReference.IsAlive);

    }

}


This posting is provided "AS IS" with no warranties, and confers no rights.

Comments

  • Anonymous
    September 23, 2007
    You've been kicked (a good thing) - Trackback from DotNetKicks.com

  • Anonymous
    September 30, 2007
    I received some feedback on my previous post A good reason for calling GC.Collect() basically saying