В реализации метода Dispose (bool) не следует ли устанавливать элементы в null? - PullRequest
4 голосов
/ 19 января 2009

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

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

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

Что вы думаете по этому поводу?

Ответы [ 3 ]

6 голосов
/ 19 января 2009

Освобождение любых дополнительных ссылок во время 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()) - так вкратце: не делайте ничего из этого во время очистки ГХ.

1 голос
/ 19 января 2009

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

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

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

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

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

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

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

0 голосов
/ 19 января 2009

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

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

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

...