Assuming this as the traditional Dispose pattern (taken from devx but seen on many websites)
class Test : IDisposable
{
private bool isDisposed = false;
~Test()
{
Dispose(false);
}
protected void Dispose(bool disposing)
{
if (disposing)
{
// Code to dispose the managed resources of the class
}
// Code to dispose the un-managed resources of the class
isDisposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
I don't understand why we call GC.SupressFinalize(this)
. This requires me to write my own managed resource disposal, including nulling my references? I'm a bit lost, I must admit. Could someone shed some light on this pattern?
Ideally, I would like to only dispose my unmanaged resources and let the GC do the managed collecting by itself.
Actually, I don't even know why we specify a finalizer. In any case, the coder should call dispose himself, now shouldn't he? If that's just a fallback mechanism, I'd remove it.
The SuppressFinalize call exists in case some derived class decides to add a finalizer. If a normal dispose completes successfully, finalization won't be necessary; even if a derived class decides to add one, the SuppressFinalize call will prevent it from executing and interfering with garbage collection.
To understand why this is important, you should think of finalization not as being part of garbage collection, but rather something that happens before it. When a class registers for finalization (automatic on creation, if it overrides Finalize) it is put into a special list called the Finalization Queue. No object in the Finalization Queue, nor any object referenced directly or indirectly by an object in the queue, can be garbage-collected, but if any object in the finalization queue is found to have no rooted references other than from the queue, the object will be pulled from the queue and the finalizer will run. While the finalizer is being dispatched, the object will not be collectable (since a reference will exist during the dispatch); once the finalizer is complete, there will usually not be any references to the object anymore, so it (and objects referenced thereby) will usually be collectable.
Personally, I think the SuppressFinalize is silly, since I can think of no good reason why a derived class should ever have a finalizer. If a derived class is going to add souse unmanaged resources(*) which the parent class will know nothing about, another class should be created for the purpose of holding those resources; the parent class should hold a reference to that. That way, the parent class itself will not need finalization, and objects which are referenced by the parent class won't be needlessly blocked from garbage collection.
From https://msdn.microsoft.com/en-us/library/system.gc.suppressfinalize(v=vs.110).aspx
As noted on MSDN executing the Finalize method is costly. By calling dispose you've already self finalized your class so the finalizer doesn't need to be called. The finalizer is implemented in case the Dispose is never called directly by your code (or whoever 'owns' the instance).
The
IDisposable
pattern is used so that the object can clean up its resources deterministically, at the point when theDispose
method is called by the client code.The finaliser is only there as a fallback in case the client code fails to call
Dispose
for some reason.If the client code calls
Dispose
then the clean-up of resources is performed there-and-then and doesn't need to be done again during finalisation. CallingSuppressFinalize
in this situation means that the object no longer incurs the extra GC cost of finalisation.And, if your own class only uses managed resources then a finaliser is completely unnecessary: The GC will take care of any managed resources, let those resources themselves worry about whether they need a fallback finaliser. You should only consider a finaliser in your own class if it directly handles unmanaged resources.
SuppressFinalize only suppresses any custom finalizer.
It does not alter any other GC behavior.
You never need to explicitly null out references. (Unless you want them to be collected early)
There is no difference between a class without any finalizer and an instance on which you've called
SuppressFinalize
.Calling
SuppressFinalize
prevents an extra call toDispose(false)
, and makes the GC somewhat faster. (finalizers are expensive)Note that classes without unmanaged resources should not have a finalizer. (They should still call
SuppressFinalize
, unless they're sealed; this allows inherited classes to add unmanaged resources)From Msdn : " This method sets a bit in the object header, which the system checks when calling finalizers. The obj parameter is required to be the caller of this method. Objects that implement the IDisposable interface can call this method from the IDisposable.Dispose method to prevent the garbage collector from calling Object.Finalize on an object that does not require it. "
So it prevents an extra call from the GC. If it is called from within the the finalizer method, when object is being finalized, then it wont do anything, as it is already being finalised. Otherwise, the GC is allowed to reclaim memory, without finalisation of the object, thus making things faster.