Как вы "правильно" реализуете 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 независимо?
2 ответа
SuppressFinalize()
не имеет смысла, если у вашего экземпляра нет финализатора.
Если в вашем классе нет финализатора, но его нет sealed
, ты должен еще SuppressFinalize
В случае, если унаследованный класс добавляет финализатор.
Оба ваших варианта верны, за исключением того, что Dispose(bool)
должно быть protected virtual
,
В вашей опции "реализовать часть типичного шаблона" вы должны сделать Dispose(bool)
метод protected virtual
:
protected virtual void Dispose(bool disposing)
{
}
Это даст подклассам возможность распоряжаться любыми ресурсами, которыми они управляют. Это означает "переопределяемый" в "Обеспечить переопределяемую реализацию Dispose (bool)"
Конечно, public virtual
также удовлетворит FxCop.