В реализации метода Dispose (bool), Должен ли один набор членов иметь значение null?

Ни один из руководств/заметок/статей, в которых обсуждается шаблон IDisposable, не предполагает, что внутренние элементы должны быть установлены в null в методе Dispose(bool) (особенно, если они являются звериными животными).

Я осознал важность этого при отладке встроенного инструмента тестирования. Случилось так, что в этом буфере содержался большой массив. Мы использовали статический буфер для всей тестовой программы. Как только мы закончим с буфером, мы не смогли бы освободить этот внутренний массив, и мы не могли бы сделать этот буфер выпущенным (как это было статично).

Итак, я считаю, что после вызова Dispose() класс должен делать все возможное, чтобы он освобождал все ресурсы, которые он использует, и делал их доступными снова, даже если сам объект, находящийся в распоряжении, не собирается обратно по GC, и не устанавливая члены в null, тем самым не позволяя собирать внутренние объекты GC, означает, что реализация Dispose не идеальна.

Каково ваше мнение об этом?

Ответ 1

Освобождение любых дополнительных ссылок во время Dispose, конечно же, я пытаюсь сделать по двум причинам:

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

Например, я обычно использую такие вещи, как:

if(someDisposableObject != null)
{
    someDisposableObject.Dispose();
    someDisposableObject = null;
}
(for non-disposable, just set to null)
someNonDisposableObject = null; // etc

Вы также можете установить любые события в null:

someEventHandler = null;

Это может помочь свести к минимуму воздействие, если вызывающий абонент не может полностью освободить свою ссылку (или просто забыть) на данный момент. Хотя вы должны попытаться освободить внешний объект (для GC), относительно легко случайно продлить срок службы объекта, например, через захваченную переменную (анонимный метод/лямбда), событие и т.д.

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

Ответ 2

Возможно, мне не хватает вашей точки, но после того, как ваш объект удален, корневой или "под-корень", который он представляет относительно его членов, был отсоединен. Похоже, вы думаете о сборке мусора, как система подсчета количества ссылок (что можно сделать, но... обычно это не так).

Вместо этого подумайте об этом как о многокорневом дереве, где каждый объект имеет ветки для того, к чему он привязан. В конце дня "конечные корни" - это статика и все, что было создано из "основной" петли.

Когда сборщик мусора работает, самый простой способ подумать о том, что он делает, - это рассмотреть список "настоящих корней" и применить "цвет" ко всему, что он может "достичь".

Теперь предположим, что коллекционер имеет доступ к "всем", независимо от того, было ли оно укоренено или нет. Все, что не окрашено, можно очистить.

Возвращаясь к исходному вопросу, когда ваш объект расположен, вы предполагаете (или, по крайней мере, надеетесь), что никто больше не ссылается на него. Если это так, оно больше не укоренено, и поэтому оно не будет способствовать "раскрашиванию" всего, что он затрагивает.

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

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

Ответ 3

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

В LOH есть хорошая статья, которая более подробно освещена здесь:

http://msdn.microsoft.com/en-us/magazine/cc534993.aspx