# Monday, 31 December 2007
« Hello World | Main | Argh! Part 2 »
Argh!
using System;

class
Program
{
    WeakReference wr;

    Program()
    {
        wr = new WeakReference(this, true);
        GC.SuppressFinalize(wr);
    }

    ~Program()
    {
        Console.WriteLine(wr.IsAlive);
    }

    static void Main()
    {
        new Program();
        GC.Collect();
        GC.WaitForPendingFinalizers();
    }
}
 

What should the output of this program be? On .NET 1.1 it's True (as expected), but on .NET 2.0 it is False. On .NET 2.0 the GC has special support for finalizing WeakReferences, but it fails to take into account whether GC.SuppressFinalize() has been called (and this may be by design, but it's still broken).

This may look academic, but it is actually a real issue in the implementation of ReferenceQueues on IKVM. Previously I used GCHandle to keep a weak reference back to the reference object that was being monitored, but because that requires full trust, I changed the code to use WeakReference, but that broke it because of the above mentioned behavior. The work around is easy, but ugly and inefficient, simply keep these weak references in a global hashtable to make sure they are always strongly reachable.

.NET really needs a better mechanism for doing post-mortem cleanup (i.e. something like java.lang.ref.ReferenceQueue).

P.S. By my new policy, I won't be filing a bug with Microsoft since they have amply demonstrated not to care about external bug reports.

Monday, 31 December 2007 14:33:49 (W. Europe Standard Time, UTC+01:00)  #    Comments [6]