Итак, реализация по умолчанию шаблон размещения выглядит следующим образом:
class SomeClass : IDisposable
{
// Flag: Has Dispose already been called?
bool disposed = false;
// Public implementation of Dispose pattern callable by consumers.
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
// Protected implementation of Dispose pattern.
protected virtual void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing) {
// Free any other managed objects here.
}
// Free any unmanaged objects here.
disposed = true;
}
~SomeClass()
{
Dispose(false);
}
}
Говорят, что:
Если вызов метода поступает из финализатора (то есть, если
false
), выполняется только код, освобождающий неуправляемые ресурсы. Так как
порядок, в котором сборщик мусора уничтожает управляемые объекты
во время финализации не определено, вызывая эту Dispose
перегрузку с
значение false
не позволяет финализатору пытаться выпустить управляемый
ресурсы, которые, возможно, уже были восстановлены.
Вопрос: почему предполагается, что объекты, на которые ссылается объект SomeClass
, возможно, уже были освобождены, и мы не должны пытаться утилизировать их, когда метод вызывается из финализатор? Если на эти объекты все еще ссылается наш SomeClass
объект, они не могут быть освобождены, не правда ли? Говорят, что:
Те, кто с ожидающими (не запущенными) финализаторами остаются в живых (пока) и
поставить на особую очередь. [...] Перед финализатором каждого объекта
работает, это все еще очень живо - эта очередь действует как корень
объект .
Итак, опять же, на наш SomeClass
объект ссылается эта очередь (что совпадает с тем, на который ссылается корень). И другие объекты, на которые ссылается объект SomeClass
, также должны быть живы (так как они внедрены через объект SomeClass
). Тогда почему и как они могли быть освобождены к моменту вызова финализатора SomeClass
?