Вопрос

Я использую шаблон реализации 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 (isDispositing)» защищенного метода после удаления управляемых ресурсов.

Так:

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

           GC.SuppressFinalize(this);
       }

       //cleanup unmanaged resources

       this.disposed = true;
    }
}
Это было полезно?

Решение

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

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

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

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

Идея состоит в том, что ваш код очистки следует вызывать только один раз.Однако есть две точки входа:тот 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. 
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top