为什么在处理对象后需要将此变量设置为null?

时间:2013-05-15 13:36:37

标签: c# dispose

PowerShell here上的文档中包含以下有趣的评论:

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

3 个答案:

答案 0 :(得分:16)

这不是直接的PowerShell问题。当using块终止时,指定的对象调用其Dispose()方法。这些通常会执行一些清理操作,通常是为了避免泄漏内存等等。但是,Dispose()不会删除该对象。如果对它的引用仍然存在于using块之外(如本示例所示),则对象本身仍在范围内。它不能被垃圾收集,因为它仍然有一个引用它,所以它仍然占用内存。

他们在你的例子中正在做的是删除该引用。当powershell设置为null时,它指向的PowerShell对象是孤立的,因为没有其他变量引用它。一旦垃圾收集器发现它,就可以释放内存。无论如何,这将发生在方法的最后(因为powershell将超出范围),但这样可以更快地恢复系统资源。

编辑:正如Brian Rasmussen指出的那样,.NET运行时对垃圾收集非常聪明。一旦它到达代码中对powershell的最后一个引用,运行时应该检测到你不再需要它并释放它以进行垃圾收集。所以powershell = null;行实际上并没有做任何事情。)

顺便说一句,这个模式对我来说很奇怪。通常的做法是这样的:

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

这样,powershell块在using块的末尾超出范围,就在它被处置之后。更容易分辨变量的相关位置,并保存一些代码,因为您不再需要powershell = null行。我甚至说这是更好的编码实践,因为powershell永远不会存在于已处置状态。如果有人修改了您的原始代码并尝试在powershell块之外使用using,则无论发生什么都可能不好。

答案 1 :(得分:7)

它不需要设置为null,它确实不应该。即使您的代码没有为相应的变量赋值空值,.NET垃圾收集器也能够检测到特定指令后未使用的对象。 (有关详细信息,请参阅http://blogs.msdn.com/b/cbrumme/archive/2003/04/19/51365.aspx。)至于为什么“官方”示例包含带有误导性评论的额外代码,甚至文档也可能存在错误...

答案 2 :(得分:1)

建议不正确,只要它无法访问它就有资格进行垃圾回收。 (请参阅What is the correct way to free memory in C#了解一些代码的代码)的唯一原因是

  • 为了更容易解决内存泄漏问题
  • 删除GC可能无法确定无法访问的引用(例如公共属性)

你真的只在对象Dispose方法

中做这两件事