Reputation: 82287
Garbage Collection can become a time consuming process. In this regard, the GC tends to work only when it has to. If an object has been disposed, to help save time and aid the GC, should the GC's finalizer be suppressed?
using(var sO = new someObject())
{
//work with object
}
public class someObject : IDisposable
{
internal Stream someResource;
internal Context someContext;
public void Dispose()
{
someContext.Dispose();
someResource.Dispose();
//A: does suppressing the GC finalizer here save time for the GC?
//B: can this cause memory leaks?
//GC.SuppressFinalize(this);
}
}
Upvotes: 4
Views: 387
Reputation: 81159
One point not yet mentioned: an object need only be considered "live" if there is some execution path via which code might need to access its fields or its object header (a data structure that holds information about the object's type, whether it's been used as a monitor lock, etc.) If an object field holds an unmanaged handle and the last thing the Dispose
method does is to close the handle, it's possible that the object may become eligible for finalization while the Dispose
method is running. Oops. Not only will the call to GC.SuppressFinalize
serve to prevent the finalizer from getting enqueued after it executes; its placement as the last thing Dispose
does will prevent the object from becoming eligible for finalization before it executes.
Upvotes: 1
Reputation: 311526
To clear up some confusion:
You only need a finalizer if you need to clean up unmanaged resources in some special way.
If you have no unmanaged resources, then you don't need a finalizer.
If you have a finalizer, then you should definitely implement IDisposable.
If you have a finalizer, then you should call GC.SuppressFinalize in Dispose, because the finalizer doesn't need to be called if you've already cleaned up after yourself.
You only need to call GC.SuppressFinalize if you have a finalizer. If you don't, you probably still want to call it anyway as a defensive measure.
does suppressing the GC finalizer here save time for the GC?
If there are unmanaged resources and your object has a finalizer, then yes; your object might live a long time on the finalization queue if you don't suppress this. The resources you dispose of may also take a long time to finalize (closing an expensive I/O channel, for example).
If you don't have a finalizer, you're saying that you don't have anything unmanaged to clean up. You should still call SuppressFinalize anyway as a defensive measure.
From the FxCop rules:
"Failure to suppress finalization degrades performance and provides no benefits."
For your other question,
can this cause memory leaks?
In this example, yes, if any of the resources are unmanaged. If your object is terminated in some unusual way before it has a chance to invoke Dispose
, unmanaged resources won't be properly freed. Consider what happens if someResource
is unmanaged and throws an exception while you're using a someObject
instance, for example.
If your object holds onto unmanaged resources and you need to guarantee those resources are cleaned up, you need a finalizer too (which would be named ~someObject
in your case).
Upvotes: 4
Reputation: 754753
If you actively Dispose
an object then yes you should suppress the finalization. There is no need for the object to be finalized if you actively / deterministically release all of the resources. Letting it hang around for the finalizer is just wasting time later on.
Upvotes: 3