Why is finalizer called on object

Here is example program that exhibits surprising finalization behavior:

class Something
{
    public void DoSomething()
    {
        Console.WriteLine("Doing something");
    }
    ~Something()
    {
        Console.WriteLine("Called finalizer");
    }
}

namespace TestGC
{
    class Program
    {
        static void Main(string[] args)
        {
           var s = new Something();
           s.DoSomething();
           GC.Collect();
           //GC.WaitForPendingFinalizers();
           s.DoSomething();
           Console.ReadKey();
        }
    }
}

If I run the program, what gets printed is:

Doing something
Doing something
Called finalizer

This appears as expected. Because there is a reference to s after the call to GC.Collect(), s is not a garbage.

Now remove comments from the line //GC.WaitForPendingFinalizers(); build and run the program again.

I would expect nothing to change in the output. This because I read that if object is found to be a garbage and it has a finalizer, it will be put on finalizer queue. Since object is not a garbage, then is seems logical that it should not be put on finalizer queue. Thus the line commented out should do nothing.

However, the output of the program is:

Doing something
Called finalizer
Doing something

Can somebody help my understanding of why finalizer gets called?

Jon Skeet
people
quotationmark

I can't reproduce the problem on my laptop, but your DoSomething method doesn't use any fields within the object. That means that the object can be finalized even while DoSomething is running.

If you change your code to:

class Something
{
    int x = 10;

    public void DoSomething()
    {
        x++;
        Console.WriteLine("Doing something");
        Console.WriteLine("x = {0}", x);
    }
    ~Something()
    {
        Console.WriteLine("Called finalizer");
    }
}

... then I suspect you will always see DoingSomething printed twice before "Called finalizer" - although the final "x = 12" may be printed after "Called finalizer".

Basically, finalization can be somewhat surprising - I very rarely find myself using it, and would encourage you to avoid finalizers wherever possible.

people

See more on this question at Stackoverflow