Ready, Compiler, Switch...
I just re-learned a valuable lesson. I was preparing for an upcoming class that I’m teaching on .NET for my team, and I was reviewing the .NET Garbage collector. I thought that I’d throw together a few quick apps using WeakReferences to show when objects are garbage collected, but I wasn’t getting the behavior I was expecting. Unless an object was explicitly set to null, the objects were not being collected. I was amazed, as this really isn’t how GC is documented, and both of my Heroes, Software Legend Jeffrey Richter and Father of COM (is Love) Don Box clearly state in their books that objects are eligible for GC after their last reference.
Well, I threw together the following code in the
Console.WriteLine("Starting GC Example App...");
object gcTestObjectWithNull = new object();
object gcTestObject = new object();
WeakReference wr = new WeakReference(gcTestObject);
WeakReference wrWithNull = new WeakReference(gcTestObjectWithNull);
Console.WriteLine( "wr.IsAlive= " + wr.IsAlive );
Console.WriteLine( "wrWithNull.IsAlive= " + wrWithNull.IsAlive );
gcTestObjectWithNull = null;
GC.Collect();
Console.WriteLine("\nWe've just garbage collected, and \n");
Console.WriteLine( "wr.IsAlive= " + wr.IsAlive );
Console.WriteLine( "wrWithNull.IsAlive= " + wrWithNull.IsAlive );
My (unexpected) output was consistently:
Starting GC Example App...
wr.IsAlive= True
wrWithNull.IsAlive= True
We've just garbage collected, and
wr.IsAlive= True
wrWithNull.IsAlive= False
Well, this would certainly contradict the GC documentation, wouldn’t it? Note that the object that is getting collected is set to null, while the object that sticks around is not.
As I’m writing up my blog findings, ready to jump on the Paul Wilson “null is necessary” bandwagon, it suddenly strikes me – I’ve been doing all this testing in DEBUG mode. A quick build of the same project in RELEASE results in:
Starting GC Example App...
wr.IsAlive= True
wrWithNull.IsAlive= True
We've just garbage collected, and
wr.IsAlive= False
wrWithNull.IsAlive= False
Ahh, now there’s the predictable behavior that I’ve been looking for! What a difference a compiler switch makes! I'll step back off Paul's null bandwagon for the moment ;-)
--