Когда следует использовать GC.SuppressFinalize()?

В .NET, при каких обстоятельствах я должен использовать GC.SuppressFinalize()?

Какое преимущество использует этот метод?

Ответы

Ответ 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

Ответ 2

вы сообщаете системе, что все, что было сделано в финализаторе, уже сделано, поэтому финализатор не нужно вызывать. Из документов .NET:

Объекты, реализующие IDisposable интерфейс может вызвать этот метод из метод IDisposable.Dispose для предотвратить сборщик мусора из вызов Object.Finalize на объект, который этого не требует.

В общем, большинство методов Dispose() должны иметь возможность вызвать GC.SupressFinalize(), потому что он должен очистить все, что было бы очищено в финализаторе.

SupressFinalize - это всего лишь то, что обеспечивает оптимизацию, которая позволяет системе не беспокоиться о том, чтобы вырезать объект в поток финализатора. Правильно написанный Dispose()/finalizer должен работать правильно с вызовом или без вызова GC.SupressFinalize().

Ответ 3

Как правило, при реализации шаблона IDisposable, когда вам не нужно завершать свой объект. Посмотрите http://www.blackwasp.co.uk/IDisposable.aspx для примеров.

Ответ 4

Этот метод должен быть вызван методом Dispose объектов, реализующих IDisposable, таким образом, GC не будет вызывать финализатор в другое время, если кто-то вызывает метод Dispose.

Смотрите: http://msdn.microsoft.com/en-us/library/system.gc.suppressfinalize.aspx