Как вы "правильно" реализуете Dispose() (согласно FxCop), когда ваша реализация является пустым методом? (CA1063)
У меня есть реализация интерфейса, и этот интерфейс расширяет IDisposable
. В моей конкретной реализации интерфейса мне не нужно ничего распоряжаться, поэтому у меня просто есть пустой метод Dispose()
.
public interface IMyStuff : IDisposable
{
}
public MyStuffImpl : IMyStuff
{
public void Dispose()
{
}
}
Теперь в FxCop это приведет к 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."
}
Итак, похоже, что я могу решить это одним из двух способов:
Сделайте класс sealed
:
public sealed MyStuffImpl : IMyStuff
{
public void Dispose()
{
}
}
Реализуйте часть типичного шаблона:
public MyStuffImpl : IMyStuff
{
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
}
}
В моем случае я не планирую, чтобы эта реализация постоянно расширялась, поэтому я, вероятно, разрешу ее, сделав ее sealed
, но я признаю, что я действительно не понимаю, почему это важно, если она запечатана или нет.
Кроме того, только потому, что мой класс запечатан, FxCop больше не говорит мне, что Dispose()
должен вызывать GC.SupressFinalize(this);
, но это правда? Это "лучше" в .NET, чтобы просто вызвать SupressFinalize в Dispose независимо?
Ответы
Ответ 1
SuppressFinalize()
не имеет смысла, если у вашего экземпляра нет финализатора.
Если ваш класс не имеет финализатора, но не sealed
, вы все равно должны SuppressFinalize
, если унаследованный класс добавляет финализатор.
Оба из ваших параметров верны, за исключением того, что Dispose(bool)
должен быть protected virtual
.
Ответ 2
В вашей опции "реализовать часть типичного шаблона" вы должны сделать свой метод Dispose(bool)
protected virtual
:
protected virtual void Dispose(bool disposing)
{
}
Это предоставит подклассам возможность обрабатывать распоряжение любыми ресурсами, которыми они управляют. То, что значение "overridable" в "Обеспечить чрезмерную реализацию Dispose (bool)"
Конечно, public virtual
также удовлетворяет FxCop.