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?
Asked
Active
Viewed 4,874 times
10

David Schmitt
- 58,259
- 26
- 121
- 165
-
If you stick to the prescribed pattern for IDisposable, I'm sure that unit testing it is going to be that useful. – Mitch Wheat Oct 29 '08 at 10:49
-
sorry, that should have been "I'm not sure that unit testing it is going to be that useful... – Mitch Wheat Oct 29 '08 at 10:58
-
@Mitch: implementing IDisposable correctly, so that managed and unmanaged resources are disposed of at the right moment is not trivial. As the library code in question is responsible for exactly that I don't see a point in _not_ testing that ... – David Schmitt Oct 29 '08 at 11:01
-
http://stackoverflow.com/a/17014062/339384 – constructor Apr 27 '15 at 11:17
4 Answers
8
No, the GC.Collect() call is asynchronous, you would also need to call this:
System.GC.WaitForPendingFinalizers();

RickL
- 2,811
- 3
- 22
- 35
-
1I 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 Oct 29 '08 at 11:06
-
I'm doing both now and the test passed every time. That is, called the correct extension point from the finalizer. – David Schmitt Oct 29 '08 at 21:53
-
Note to self: also check that the initialisation code of the class in question doesn't "root" the object somewhere. – David Schmitt Oct 30 '08 at 21:39
-
@EricBurcham: an example where I use that is here: https://github.com/daszat/zetbox/blob/master/Tests/DisposableMockTemplate.cs – David Schmitt Feb 19 '14 at 14:54
-
this doesn't work for me. I called `GC.Collect()` and then `GC.WaitForPendingFinalizers();` and at no point is `disposing` ever `false` – Matthew Jul 24 '19 at 20:32
2
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
- 1,909
- 1
- 19
- 20
-
Yeah, I'm doing it quite like that. It's only a slight adaptation of what's recommended in the MSDN. – David Schmitt Feb 12 '09 at 07:52
0
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
- 4,400
- 4
- 30
- 32
-
Setting a breakpoint is sufficient to discover that. I'm testing the Dispose()'s implementation though, not whether it's called. – David Schmitt Jan 24 '09 at 20:12
0
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
- 3,988
- 3
- 19
- 35