GC.SuppressFinalize

Fun With GC.SuppressFinalize

I was able to get Fedora Core 6 running very well on Microsoft’s Virtual PC 2007 with just two small tweeks. The main problem is the emulated S3 video card doesn’t support 24 bpp mode, whereas the actual hardware card does! I wish I could find the blog or newsgroup post that I found that originally pointed this out so I could give credit to whoever figured this out — thanks! If you know please contact me and I’ll update the blog post.

Here’s all that i had to do:

Run the install in text mode. You do this by entering “linux text” without the quotes at the initial prompt.
When Fedora boots:
Login
vi /etc/X11/xorg.confWhile discussing some code with a colleague, I ran across an unexpected behavior of GC.SuppressFinalize. I’ve put together a small sample for our discussion.

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1
{
public class Base
{
~Base()
{
Console.WriteLine(“Base Finalizer called”);
}
}

public class Derived : Base
{
~Derived()
{
Console.WriteLine(“Derived Finalizer called”);
}

public void Suppress()
{
GC.SuppressFinalize(this);
}

}

class Program
{
static void Main(string[] args)
{
Derived d = new Derived();
d.Suppress();

Console.ReadLine();
}
}
}
Okay, so what gets printed out at the console?

Actually, nothing.

It was a little surprising to me at first, especially since after years of C++ programming the ~ immediately invokes destructor semantics in my head. I worked through a number of different variations, but I always got the same result. I used the !FinalizeQueue command available in the SOS extension of WinDBG to verify that there was only the Derived class reference on the queue. So when you say, SuppressFinalize(this) you really mean it!

Now, granted, this is a cheesy example. But the discussion came up when talking about the correct way to implement IDisposable. In the example provided, SuppressFinalize(this) is called in the Dispose method. Now that’s a good thing, because you want to prevent the call to the finalizer since you have already cleaned up any resources via your Dispose implementation. But, what happens if a class you derived from, either your own or a third party, does not implement IDisposable and instead is relying on the finalizer? Or they do implement IDisposable but somewhere else along the virtual method override chain someone forgot to call the base class implementation.

This really never should be a problem if your code implements the IDisposable interface correctly. And since implementing a Finalizer on your class has a negative performance impact you should only use them when you really need to. Anyway, this makes a great conversation at any nerd party