Ok, it's known that GC implicitly calls Finalize
methods on objects when it identifies that object as garbage. But what happens if I do a GC.Collect()
? Are the finalizers still executed? A stupid question maybe, but someone asked me this and I answered a "Yes" and then I thought: "Was that fully correct?"
Ok, it's known that GC implicitly calls Finalize methods on objects when it identifies that object as garbage.
No no no. That is not known because in order to be knowledge a statement must be true. That statement is false. The garbage collector does not run finalizers as it traces, whether it runs itself or whether you call Collect
. The finalizer thread runs finalizers after the tracing collector has found the garbage and that happens asynchronously with respect to a call to Collect
. (If it happens at all, which it might not, as another answer points out.) That is, you cannot rely on the finalizer thread executing before control returns from Collect
.
Here's an oversimplified sketch of how it works:
As I said, that's oversimplified; the exact details of how the finalizer queue works are a bit more complicated than that. But it gets enough of the idea across. The practical upshot here is that you cannot assume that calling Collect
also runs finalizers, because it doesn't. Let me repeat that one more time: the tracing portion of the garbage collector does not run finalizers, and Collect
only runs the tracing part of the collection mechanism.
Call the aptly named WaitForPendingFinalizers
after calling Collect
if you want to guarantee that all finalizers have run. That will pause the current thread until the finalizer thread gets around to emptying the queue. And if you want to ensure that those finalized objects have their memory reclaimed then you're going to have to call Collect
a second time.
And of course, it goes without saying that you should only be doing this for debugging and testing purposes. Never do this nonsense in production code without a really, really good reason.