I have an implementation of an interface, and that interface extends IDisposable
. In my particular implementation of the interface, I don't need to dispose anything, so I just have an empty Dispose()
method.
public interface IMyStuff : IDisposable
{
}
public MyStuffImpl : IMyStuff
{
public void Dispose()
{
}
}
Now in FxCop, this results in a CA1063:
Error, Certainty 95, for ImplementIDisposableCorrectly
{
Resolution : "Provide an overridable implementation of Dispose(
bool) on 'MyStuffImpl' or mark the type as sealed.
A call to Dispose(false) should only clean up native
resources. A call to Dispose(true) should clean up
both managed and native resources."
}
CriticalWarning, Certainty 75, for CallGCSuppressFinalizeCorrectly
{
Resolution : "Change 'MyStuffImpl.Dispose()' to call 'GC.SuppressFinalize(
object)'. This will prevent derived types that introduce
a finalizer from needing to re-implement 'IDisposable'
to call it."
}
Error, Certainty 95, for ImplementIDisposableCorrectly
{
Resolution : "Modify 'MyStuffImpl.Dispose()' so that it
calls Dispose(true), then calls GC.SuppressFinalize
on the current object instance ('this' or 'Me' in Visual
Basic), and then returns."
}
So, it looks like I can resolve this in one of 2 ways:
Make the class sealed
:
public sealed MyStuffImpl : IMyStuff
{
public void Dispose()
{
}
}
Implement part of the typical pattern:
public MyStuffImpl : IMyStuff
{
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
}
}
In my case, I don't plan on this implementation ever being extended, so I will probably resolve it by making it sealed
, but I admit I don't really understand why it matters if it is sealed or not.
Also, just because my class is sealed, FxCop no longer tells me that Dispose()
should call GC.SupressFinalize(this);
but is that really true? Is it "better" in .NET to just always call SupressFinalize in Dispose regardless?
SuppressFinalize()
is meaningless unless your instance has a finalizer.
If your class doesn't have a finalizer, but is not sealed
, you should still SuppressFinalize
, in case an inherited class adds a finalizer.
Both of your options are correct, except that Dispose(bool)
needs to be protected virtual
.
In your "implement part of the typical pattern" option, you should make your Dispose(bool)
method protected virtual
:
protected virtual void Dispose(bool disposing)
{
}
That will provide subclasses an opportunity to handle disposal of any resources they manage. That's the meaning of "overridable" in "Provide an overridable implementation of Dispose(bool)"
Of course, public virtual
would also satisfy FxCop.
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