Bring out your dead

Something that has been missing for the .NET framework for a while is a weak hashtable. This kind of datatype is useful as it allows you to associate data with an object in a way that allows the data to be thrown away if the object is garbage collected. The problem here is that we don’t want the presence of the object as a hashtable key to keep the object alive and we don’t want to add any fields to the object to hold this data.

.NET 4 has a new ConditionalWeakTable type that addresses some of these problems. It isn’t a true Dictionary as it only supports reference equality, but it is useful for storing this extra information; I think that the MEF framework uses the type for this purpose.

We can quickly test this type by defining an object that has a name and prints out a message when it is finalised.

class Probe
     public string Name { get; set;  }
     public Probe(string name)
         Name = name;
         Console.WriteLine("Finalizer called on {0}", Name);

We can build a weak table suitable for holding these probes.

static ConditionalWeakTable<Probe,Probe> s_TestTable = new ConditionalWeakTable<Probe, Probe>();

We’ll use a simple function for populating the table – we don’t want the lifetime of local variables affecting the garbage collection.

static Probe Populate()
    Probe key1 = new Probe("permanent");
    Probe key2 = new Probe("Temporary");
    Probe data1 = new Probe("Data1");
    Probe data2 = new Probe("Data2");
    s_TestTable.Add(key1, data1);
    s_TestTable.Add(key2, data2);
    return key1;

The GetValue method also needs a delegate for returning a default if the key is not found in the table.

static Probe Default()
    throw new Exception("Not found");

We can now run a small example, which fills the table with two keys and associated data. We keep hold of one of the keys while we do a garbage collection, and we see the other key and its associated datum are collected. When the program finishes, we see the other key and value getting collected.

static void Main(string[] args)
    Probe key1 = Populate();
    Console.WriteLine("Object alive: {0}", s_TestTable.GetValue(key1, _ => Default()).Name);

Running this we get the output.

Finalizer called on Data2
Finalizer called on Temporary
Object alive: Data1
Finalizer called on Data1
Finalizer called on permanent

This entry was posted in Computers and Internet. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s