IDisposable GC.SuppressFinalize(это) местоположение

Я использую шаблон (шаблон) для IDisposable по умолчанию для моего кода.

сниппет:

public void Dispose()
{
    Dispose(true);

    GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool isDisposing)
{
    if (!this.disposed)
    {
        if (isDisposing)
        {
            //cleanup managed resources
        }

        //cleanup unmanaged resources

        this.disposed = true;
    }
}

Мой вопрос: почему вызов "GC.SuppressFinalize(this)" в публичном методе Dispose? Я бы поставил "GC.SuppressFinalize(this)" в разделе "if (isDisposing)" защищенного метода после удаления управляемых ресурсов.

Вот так:

protected virtual void Dispose(bool isDisposing)
{
    if (!this.disposed)
    {
       if (isDisposing)
       {
           //cleanup managed resources

           GC.SuppressFinalize(this);
       }

       //cleanup unmanaged resources

       this.disposed = true;
    }
}

Ответ 1

Я полагаю, что это явный случай шаблона шаблона дизайна.

Ваш абстрактный класс предназначен для выполнения всех важных/необходимых задач (здесь GC.SuppressFinalize(this)) и позволяет производному классу переопределить только часть кода.

Здесь два случая:
Фрагмент 1, SuppressFinalize, в утилите
Snippet 2, SuppressFinalize, в Dispose (true)

Здесь, Snippet 1, убедитесь, что GC.SuppressFinalize всегда выполняется. В то время как фрагмент 2 оставляет выполнение GC.SuppressFinalize по милости производного класса.

Итак, поставив GC.SuppressFinalize, в методе Dispose вы как разработчик своего класса всегда будете уверены, что независимо от того, какой код написан производными классами, GC.SuppressFinalize будет выполнен.

Это только преимущество написания SuppressFinalize в Dispose, а не Dispose (true).

Ответ 2

Метод Dispose(bool isDisposing) не является частью интерфейса IDisposable.

Обычно вы вызываете Dispose(true) из своего метода Dispose и вызываете Dispose(false) из вашего финализатора, как резерв в если объект еще не был удален.

Вызов SuppressFinalize сообщает GC, что нет необходимости вызывать финализатор вашего объекта, предположительно потому, что вся ваша очистка выполнялась, когда Dispose был вызван.

Если у вас нет финализатора на вашем классе, вам не нужно вообще называть SuppressFinalize, так как нет финализатора для подавления!

Joe Duffy имеет несколько отличных рекомендаций по утилизации, финализации, сборке мусора и т.д..

Ответ 3

Я думаю, что любой макет мог быть выбран, но, вероятно, они хотели подчеркнуть "положить весь код освобождения в этом методе" в защищенный метод Dispose, поэтому они помещают другой артефакт распоряжения (подавление финализации) в другом месте.

Кроме того, предположим, что производный класс имел еще одну причину вызова защищенного метода Dispose, но все еще нуждался в завершении (по любой мыслимой причине, я не знаю).

Ответ 4

Причина. Задача - когда управляемый код (ваш код) удаляет объект, тем самым отказываясь от завершения. Люди обычно создают другой маршрут в Dispose (bool disposing) через финализатор, и вызов не будет иметь никакого смысла для финалиста.

Ответ 5

Идея заключается в том, что ваш код очистки должен вызываться только один раз. Однако есть две точки входа: метод Dispose и финализаторы объектов. Когда вызывается Dispose, вы отказываетесь от завершения, чтобы ваш код очистки вызывался только один раз. Код здесь может показать его лучше.

Цитата:

// NOTE: Leave out the finalizer altogether if this class doesn't 
// own unmanaged resources itself, but leave the other methods
// exactly as they are.