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 main difference between dispose() and finalize() is that the method dispose() has to be explicitly invoked by the user whereas, the method finalize() is invoked by the garbage collector, just before the object is destroyed.
Finalize gives implicit control over releasing resources. It is called by the garbage collector. Dispose is a way to give explicit control over a release of resources and can be called directly. There is much much more to learn about the subject of Garbage Collection, but that's a start.
SuppressFinalize() system method is designed to prevent calling the finalizer on the specified object. If an object does not have a destructor, invoking SuppressFinalize on this object has no effect and JetBrains Rider flags such call as redundant. To learn more how the destructor works, see Object.
Destructor implicitly calls the Finalize method, they are technically the same. Dispose is available with objects that implement the IDisposable interface. The destructor implicitly calls Finalize on the base class of the object.
The IDisposable
pattern is used so that the object can clean up its resources deterministically, at the point when the Dispose
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. Calling SuppressFinalize
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 to Dispose(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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With