I'm working on a piece of library code around IDisposable
. The managed path (via using
) is easily testable. I'm wondering about the finalizer though: Is calling System.GC.Collect()
sufficient to force the finalizer to run?
views:
528answers:
4
A:
Could you mock out an IDisposable
interface and expect a call to Dispose
? That would at least let you see when the object is actually disposed.
brien
2008-10-29 10:43:09
Setting a breakpoint is sufficient to discover that. I'm testing the Dispose()'s implementation though, not whether it's called.
David Schmitt
2009-01-24 20:12:02
+5
A:
No, the GC.Collect() call is asynchronous, you would also need to call this:
System.GC.WaitForPendingFinalizers();
RickL
2008-10-29 10:45:54
I think the GC.Collect() itself is synchronous (i.e. it will have freed any memory it can by the time it returns) but the finalizers themselves run separately. I could be entirely wrong though...
Jon Skeet
2008-10-29 11:06:44
I'm doing both now and the test passed every time. That is, called the correct extension point from the finalizer.
David Schmitt
2008-10-29 21:53:11
Note to self: also check that the initialisation code of the class in question doesn't "root" the object somewhere.
David Schmitt
2008-10-30 21:39:57
A:
I think I would lean towards making Finalize() call another method, and test that the other method does what you want. You wouldn't get 100% code coverage, but at least you'd know that the method releases the object's resources properly.
Ben Fulton
2008-10-29 21:31:04
+1
A:
I would take a look at Dispose, Finalization, and Resource Management its the best reference on the subject I know of. Using their pattern:
~ComplexCleanupBase()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected override void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
// dispose-only, i.e. non-finalizable logic
}
// new shared cleanup logic
disposed = true;
}
base.Dispose(disposing);
}
You wind up with dead simple Finalizer/Dispose() methods and a testable Dispose(bool). No need to force Finalization or anything using the GC class.
Rob McCready
2009-02-11 18:45:23
Yeah, I'm doing it quite like that. It's only a slight adaptation of what's recommended in the MSDN.
David Schmitt
2009-02-12 07:52:15