Given this code in the dispose-pattern from msdn
public class DisposableResourceHolder : IDisposable {
private SafeHandle resource; // handle to a resource
public DisposableResourceHolder() {
this.resource = ... // allocates the resource
}
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing) {
if (disposing) {
if (resource!= null) resource.Dispose();
}
}
}
Why would one call GC.SuppressFinalize(this)
if the object does not have a finalizer? If my understanding is right, the object won't even reach a finalization queue to be removed from in the first place.
And if the call to GC.SuppressFinalize(this)
is not required and we remove it then the whole pattern's benefits becomes less obvious to me. What am I missing, why is Microsoft recommending this?
Given this code in the dispose-pattern from msdn
public class DisposableResourceHolder : IDisposable {
private SafeHandle resource; // handle to a resource
public DisposableResourceHolder() {
this.resource = ... // allocates the resource
}
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing) {
if (disposing) {
if (resource!= null) resource.Dispose();
}
}
}
Why would one call GC.SuppressFinalize(this)
if the object does not have a finalizer? If my understanding is right, the object won't even reach a finalization queue to be removed from in the first place.
And if the call to GC.SuppressFinalize(this)
is not required and we remove it then the whole pattern's benefits becomes less obvious to me. What am I missing, why is Microsoft recommending this?
1 Answer
Reset to default 5The only reason to implement the "full" Dispose pattern here is in case your class has a subclass which needs it. If this happens, the subclass will override Dispose(bool)
and implement its own finalizer.
If you don't care about supporting this case (and most people don't, in practice), then you can just ditch GC.SuppressFinalize
and Dispose(bool)
:
public sealed class DisposableResourceHolder : IDisposable {
private SafeHandle resource; // handle to a resource
public DisposableResourceHolder() {
this.resource = ... // allocates the resource
}
public void Dispose() {
resource.Dispose();
}
}
(One school of thought recommends only ever using SafeHandle
or equivalent to own unmanaged resources, which means that you almost never need to implement your own finalizer, which means you can just follow the simplified Dispose pattern above everywhere).