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

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

фрагмент кода:

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;
    }
}

5 ответов

Решение

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

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

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

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

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

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

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

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

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

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

У Джо Даффи есть отличные рекомендации по утилизации, доработке, уборке мусора и т. Д.

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

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

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

Идея состоит в том, что ваш код очистки должен вызываться только один раз. Однако есть две точки входа: 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. 
Другие вопросы по тегам