Ответ 1
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, что объект был очищен должным образом и не нужно идти в очередь финализатора. Он выглядит как деструктор С++, но не действует ни на что.
Оптимизация 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