Objects can be collected while their instance methods are still executing
In Peter Ritchie’s post Dispose Pattern and “Set large fields to null”, he states the following (my highlighting):
At face value, setting a field to null means that the referenced object is now unrooted from the class that owns the field and, if that was the last root of that reference, the Garbage Collector (GC) is now free to release the memory used by the object that was referenced by that field. Although advanced, this seems all very academic because the amount of time between unrooting the reference and the return from
Dispose(and thus the unrooting of the parent object) would seem like a very short amount of time. Even if the amount of time between these two actions is small, setting a single field to null (i.e. a single assignment) seems like such a minor bit of code to provide no adverse affects. The prevalent opinion seems to be that the GC “handles” this case and does what is best for you without setting the field to null.
In fact, this “short amount of time” can be so short as to be negative! A class that nothing else refers to is unrooted as soon as it no longer refers to itself, so objects in .NET can be collected while their instance methods are still executing. I first learned about this from Chris Brumme’s blog. Here is an example that shows this behaviour:
The output is:
start method collected end method
Once the method Go() has no references to this, it is eligible for collection. (What this means is that setting fields to null will actually extend the lifetime of the parent object ever-so-slightly.)
However, the code that a using is transformed into will hold onto a reference to the object while its Dispose() method is called, so you won’t get the same behaviour with the following code:
The output is:
start method end method collected
This is because the using statement is transformed to something like this:
I think (but cannot confirm) that the reference being held is that of Slow in the outer scope. We can restore the previous behaviour if the using transform was written as this instead:
Either way, I wouldn’t bother setting fields to null in the Dispose() method. (For one thing, these fields can no longer be declared readonly.) And most of the time, the GC is smarter than you are.




