14

此处有关 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;

为什么配置后需要设置powershellnull

4

3 回答 3

17

这不是直接的 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无论发生什么都可能是坏事。

于 2013-05-15T16:31:47.493 回答
6

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

于 2013-05-15T17:15:09.093 回答
1

该建议是不正确的,只要它不可达,它就有资格进行垃圾收集。(请参阅什么是在 C# 中释放内存的正确方法以获取一些演示这一点的代码)将内容归零的唯一原因是

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

这两者你真的只能在对象Dispose方法中做

于 2013-05-16T18:38:31.287 回答