SuppressFinalize должен вызываться только классом, имеющим финализатор. Он сообщает сборщику мусора (GC), что объект this
полностью очищен.
Рекомендуемый шаблон IDisposable при наличии финализатора:
public class MyClass : IDisposable
{
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
// called via myClass.Dispose().
// OK to use any private object references
}
// Release unmanaged resources.
// Set large fields to null.
disposed = true;
}
}
public void Dispose() // Implement IDisposable
{
Dispose(true);
GC.SuppressFinalize(this);
}
~MyClass() // the finalizer
{
Dispose(false);
}
}
Обычно CLR сохраняет вкладки на объектах с помощью финализатора, когда они создаются (что делает их создание более дорогим). SuppressFinalize сообщает GC, что объект был очищен правильно, и ему не нужно идти в очередь финализатора. Он выглядит как деструктор C ++, но не действует так, как он.
Оптимизация SuppressFinalize не тривиальна, поскольку ваши объекты могут долго жить в очереди финализатора. Не поддавайтесь искушению вызвать SuppressFinalize для других объектов. Это серьезный дефект, который должен произойти.
Рекомендации по проектированию сообщают нам, что финализатор не нужен, если ваш объект реализует IDisposable, но если у вас есть финализатор, вы должны реализовать IDisposable, чтобы разрешить детерминированную очистку вашего класса.
Большую часть времени вы должны иметь возможность сойти с IDisposable для очистки ресурсов. Финализатор вам нужен только тогда, когда ваш объект удерживает неуправляемые ресурсы, и вы должны гарантировать, что эти ресурсы очищены.
Примечание. Иногда кодеры добавляют финализатор для отладки сборок своих собственных классов IDisposable, чтобы проверить, что код правильно расположил их объект IDisposable.
public void Dispose() // Implement IDisposable
{
Dispose(true);
#if DEBUG
GC.SuppressFinalize(this);
#endif
}
#if DEBUG
~MyClass() // the finalizer
{
Dispose(false);
}
#endif