Как вы «правильно» реализуете Dispose () (согласно FxCop), когда ваша реализация является пустым методом?(CA1063) - PullRequest
13 голосов
/ 21 января 2012

У меня есть реализация интерфейса, и этот интерфейс расширяет 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 ]

11 голосов
/ 21 января 2012

SuppressFinalize() не имеет смысла, если в вашем экземпляре нет финализатора.
Если в вашем классе нет финализатора, но он не sealed, вы все равно должны SuppressFinalize, если унаследованный класс добавляет финализатор.

Оба ваших варианта верны, за исключением того, что Dispose(bool) должно быть protected virtual.

2 голосов
/ 21 января 2012

В вашей опции "реализовать часть типичного шаблона" вы должны указать Dispose(bool) метод protected virtual:

protected virtual void Dispose(bool disposing) 
{ 
} 

Это даст подклассам возможность распоряжаться любыми ресурсами, которыми они управляют. Это означает «переопределяемый» в «Обеспечить переопределяемую реализацию Dispose (bool)»

Конечно, public virtual также удовлетворит FxCop.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...