GarbageCollector аннулирует поля-члены? - PullRequest
1 голос
/ 21 сентября 2011

Я отлаживаю некоторый класс C # (скажем, Foo), в котором реализован шаблон Dispose-Finalize, то есть его Finalizer вызывает Dispose () в случае, если Dispose еще не был вызван.

Внутри Dispose () есть код регистрации, который обращается к некоторому члену Foo (скажем, Bar).Bar также является экземпляром некоторого ссылочного типа, доступен только для чтения (создается в конструкторе Foo) и не отображается нигде за пределами Foo.Таким образом, во время сбора мусора Foo, вероятно, также будет собираться Bar.Теория говорит, что такие поля-члены не должны быть доступны из потока Finalize.

Но код регистрации не знал теории и пытался зарегистрировать некоторые свойства Bar.И процесс завершился с NullReferenceException в потоке Финализатора.

Я понимаю, что плохие вещи могут случиться, когда вы игнорируете теорию, но я не ожидал, что NRE: сборщик мусора отправляет ссылки на собранные объекты на нуль?Или я что-то упускаю?

1 Ответ

2 голосов
/ 21 сентября 2011

В Реализуя метод Dispose , они специально предупреждают о доступе к другим объектам из финализатора.Вот почему у них есть шаблон:

~MyObject()
{
    Dispose(false);  // False because it's being called in a finalizer
}

public void Dispose()
{
    Dispose(true);  // True because it was called from user code
    GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing)
{
    if (disposing)
    {
        // here it's safe to access other CLR objects
    }

    // Here you dispose of any unmanaged objects
}

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

Обратите также внимание, что вам не нужен финализатор, если вы не создаете класс, который выделяет неуправляемые ресурсы.Если ваш класс использует только объекты CLR или сторонние библиотеки, которые предоставляют объекты .NET, тогда финализатор не нужен.

...