Подтвердить что ты не робот

Почему эта переменная должна быть установлена ​​равной нулю после удаления объекта?

В документации по PowerShell здесь есть следующий интересный комментарий:

PowerShell powershell = PowerShell.Create();

using (powershell)
{
    //...
}

// Even after disposing of the PowerShell object, we still 
// need to set the powershell variable to null so that the 
// garbage collector can clean it up.
powershell = null;

Почему powershell нужно установить в null после размещения?

4b9b3361

Ответ 1

Это не проблема PowerShell. Когда блок using завершается, у указанного объекта (ов) есть свои методы Dispose(). Обычно они выполняют некоторые операции очистки, часто во избежание утечки памяти и т.д. Однако Dispose() не удаляет объект. Если ссылка на нее по-прежнему существует вне блока using (как в этом примере), то сам объект по-прежнему находится в области видимости. Это не может быть собрано в мусор, потому что все еще есть ссылка на него, поэтому он все еще занимает память.

Что они делают в вашем примере, это удаление этой ссылки. Если для параметра powershell установлено значение null, объект PowerShell, на который он указывал, является сиротой, поскольку нет других переменных, ссылающихся на него. Как только сборщик мусора показывает это, он может освободить память. Это все равно произойдет в конце метода (потому что powershell выйдет за рамки), но таким образом вы снова получите системные ресурсы.

( Изменить: Как указывает Брайан Расмуссен, среда выполнения .NET чрезвычайно полезна для сбора мусора. После того, как она вернется к последней ссылке на powershell в вашем коде, среда выполнения должна обнаружить, что вы больше не нужно, и отпустите его для сбора мусора. Таким образом, строка powershell = null; фактически ничего не делает.)

Кстати, этот шаблон выглядит очень странно для меня. Обычный подход выглядит примерно так:

using (PowerShell powershell = PowerShell.Create())
{
   //...
}

Таким образом, powershell выходит за пределы области действия в конце блока using, сразу после его удаления. Легче сказать, где важна переменная, и вы сохраняете некоторый код, потому что вам больше не нужна строка powershell = null. Я бы даже сказал, что это лучше практика кодирования, потому что powershell никогда не существует в уже настроенном состоянии. Если кто-то изменяет ваш исходный код и пытается использовать powershell вне блока using, все, что произойдет, вероятно, будет плохим.

Ответ 2

Не нужно устанавливать значение null, и этого действительно не должно быть. Сборщик мусора .NET вполне способен обнаруживать, что объект не используется после конкретной инструкции, даже если ваш код не присваивает нулевое значение соответствующей переменной. (Подробнее см. http://blogs.msdn.com/b/cbrumme/archive/2003/04/19/51365.aspx.) Что касается того, почему "официальный" пример содержит этот дополнительный код с вводящими в заблуждение комментариями, даже документы могут иметь ошибки...

Ответ 3

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

  • Чтобы упростить устранение утечек памяти
  • Чтобы удалить ссылки (например, общедоступные свойства), которые могут иметь проблемы с GC, недоступны

Оба из которых вы бы действительно делали только в методах Dispose объектов