IDisposable GC.SuppressFinalize(this) местоположение
-
03-07-2019 - |
Вопрос
Я использую шаблон реализации 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.