Для чего нужны финализаторы? - PullRequest
8 голосов
/ 20 апреля 2009

Я программирую в .NET уже четыре года (в основном на C #), и я широко использую IDiposable, но мне все еще не нужен финализатор. Для чего нужны финализаторы?

Ответы [ 5 ]

11 голосов
/ 20 апреля 2009

Финализатор - это последняя попытка убедиться, что что-то очищено правильно, и обычно он зарезервирован для объектов, которые обертывают неуправляемые ресурсы, такие как неуправляемые дескрипторы и т. Д., Которые не будут собирать мусор.

Редко пишется финализатор. К счастью (и в отличие от IDisposable), финализаторы не нужно распространять; так что если у вас есть ClassA с финализатором и ClassB, который включает ClassA, то ClassB не нуждается в финализаторе - но вполне вероятно, что и 1010 *, и ClassB будут реализовывать IDisposable.

Для управляемого кода обычно достаточно IDisposable. Даже если вы не очистите правильно, в конце концов, управляемые объекты будут собраны (при условии, что они освобождены).

4 голосов
/ 20 апреля 2009

Финализаторы предназначены только для освобождения неуправляемых ресурсов, таких как дескрипторы растровых изображений GDI, например. Если вы не выделяете неуправляемые ресурсы, вам не нужны финализаторы. В общем, плохая идея касаться любого управляемого объекта в финализаторе, потому что порядок финализации не гарантирован.

Еще один полезный метод, использующий финализатор, состоит в том, чтобы утверждать, что Dispose был вызван, когда для этого требуется приложение. Это может помочь отловить ошибки кодирования в сборке DEBUG:

void Dispose()
{
  GC.SuppressFinalize(this);
}
#if DEBUG
~MyClass()
{
  Debug.Fail("Dispose was not called.");
}
#endif
2 голосов
/ 20 апреля 2009

Финализаторы предназначены как механизм для освобождения ресурсов, не контролируемых сборщиком мусора, как неуправляемый дескриптор. Хотя Dispose может сделать это, не гарантируется, что потребитель позвонит.

1 голос
/ 20 апреля 2009

Википедия говорит :

... финализатор это кусок кода, который обеспечивает выполнение определенных необходимых действий принимаются, когда приобретенный ресурс ... больше не используется [потому что владение объектом было мусором собраны]

И если вы не используете финализатор при написании IDisposables, у вас вполне могут быть утечки памяти, потому что нет никакой гарантии, что владелец действительно вызовет Dispose ().

MS сами рекомендуют написать что-то похожее на эти реализации:

    public void Dispose()
    {
        this.Dispose(true);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!this.isDisposed)
        {
            if (disposing)
            {
                GC.SuppressFinalize(this);
            }
        }
        //Dispose of resources here
        this.isDisposed = true;
    }

    ~DisposableSafe()
    {
        this.Dispose(false);
    }

    private bool isDisposed = false;

Лично я терпеть не могу копирование-вставку, поэтому склоняюсь к тому, чтобы обернуть его в абстрактный класс для повторного использования.

1 голос
/ 20 апреля 2009

Финализаторы предназначены для очистки ресурсов, если они не были утилизированы.

То есть, ничто не заставляет вас вызывать Dispose (), но финализаторы вызываются сборщиком мусора автоматически.

На эту функциональность не следует полагаться, поскольку нет гарантии, когда (или если) сборщик мусора попадет к вашему объекту.

...