IDisposable GC.SuppressFinalize (это) местоположение - PullRequest
10 голосов
/ 03 марта 2009

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

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

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 ]

11 голосов
/ 03 марта 2009

Полагаю, это явный случай шаблона шаблонов.

Ваш абстрактный класс предназначен для выполнения всех необходимых / необходимых задач (здесь 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).

5 голосов
/ 03 марта 2009

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

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

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

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

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

1 голос
/ 03 марта 2009

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

1 голос
/ 03 марта 2009

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

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

0 голосов
/ 03 марта 2009

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