views:

456

answers:

4

I've got the following code :

 public class A
    {
        ~A()
        {
            Console.WriteLine("destructor");
        }
    }

 public static A Aref;
 static void Main(string[] args)
    {
        Aref = new A();
        int gen = GC.GetGeneration(Aref);
        Aref = null;
        GC.Collect(gen, GCCollectionMode.Forced);
        Console.WriteLine("GC done");

    }

I thought my Finalizer method would be called upon my call to GC.Collect, which is not the case.

Can anyone explain me why ?

+10  A: 

Finalizers aren't called before GC.Collect() returns. The finalizers are run in a separate thread - you can wait for them by calling GC.WaitForPendingFinalizers().

Jon Skeet
+6  A: 

The finalizer is not called during the collection in your example, cause it is still being rooted by the finalizable queue. It is however scheduled for finalization, which means that it will be collected during the next garbage collection.

If you want to make sure instances of types with a finalizer are collected you need to do two collections like this.

GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();

But generally you should not call the Collect() method yourself.

Brian Rasmussen
A: 

Even if you ask for the GC to collect, it is unsure that this specific object will be destroyed (as it could not be in the generation being collected at that moment)

Fabian Vilers
In this simple example the OP makes sure that relevant generation is collected. So unless there's a collection before the explicit call to Collect() it should work as expected.
Brian Rasmussen
A: 

Because you declared your variable outside of main and is static, it is not called when your expecting it. The call is made but is after the command window has closed so you can't see it. Change your declaration to this:

public static void Main()
{
    A Aref = new A();
    int gen = GC.GetGeneration(Aref);
    Aref = null;
    GC.Collect(gen, GCCollectionMode.Forced);
    Console.WriteLine("GC done");

}

P.S. There is not much use for destructors in .NET.

Lucas McCoy
That is not correct. After Aref = null there are no reference to the instance.
Brian Rasmussen