Вопрос

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

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

Это было полезно?

Решение

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

Другие советы

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

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

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

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

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

Видишь: http://msdn.microsoft.com/en-us/library/system.gc.suppressfinalize.aspx

 Dispose(true);
 GC.SuppressFinalize(this);

Если у объекта есть финализатор, .net помещает ссылку в очередь завершения

Поскольку у нас есть вызов Dispose (ture), он очищает объект, поэтому нам не нужна очередь завершения для выполнения этой работы.

Поэтому вызовите GC.SuppressFinalize(this), чтобы удалить ссылку в очереди завершения.

Если класс или что-либо производное от него может содержать последнюю текущую ссылку на объект с финализатором, то либо GC.SuppressFinalize(this) или GC.KeepAlive(this) должен вызываться для объекта после любой операции, на которую может отрицательно повлиять этот финализатор, таким образом гарантируя, что финализатор не будет запущен до завершения этой операции.

Стоимость GC.KeepAlive() и GC.SuppressFinalize(this) по существу одинаковы в любом классе, у которого нет финализатора, а классы, у которых есть финализаторы, обычно должны вызывать GC.SuppressFinalize(this), таким образом , используя последнюю функцию в качестве последнего шага Dispose() возможно, это не всегда необходимо, но в этом не будет ничего плохого.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top