2013-05-15 47 views
13

在PowerShell中here的文件中有如下有趣的评论:为什么在处理对象后需要将此变量设置为null?

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

+2

这是一个C#的问题,而不是一个PowerShell的问题。 –

+1

@AnsgarWiechers - 你是对的;但通过检查链接,这是一种奇怪的模式。任何人都可以告诉他们为什么不用'使用(PowerShell powershell = PowerShell.Create()){'?风格偏好? –

+8

对于这种记录来说,这是一种普遍不好的做法,在这种情况下完全不需要。根本不可能产生任何影响,如果可能的话,这将是微不足道的。这个变量实际上应该是在'using'内部创建的,但是即使没有这样做,也没有任何理由将它归零。该方法的其余部分将很快完成*非常*,一旦处置,powershell对象将不会占用大量资源。 – Servy

回答

16

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

他们在你的例子做什么下探该引用。当powershell设置为null时,它指向的PowerShell对象是孤立的,因为没有其他变量引用它。一旦垃圾收集器计算出来,它可以释放内存。无论如何,这会在方法结束时发生(因为powershell会超出范围),但这样您可以更快地获得系统资源。

编辑:布赖恩拉斯穆森指出,.NET运行库是关于垃圾收集绝顶聪明一旦达到你的代码中的最后一个引用powershell,运行时应该检测出你不需要它。所以powershell = null;线实际上并没有做任何事情。)

顺便说一下,这种模式看起来很奇怪。通常的做法是这样的:

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

这样,powershell超出范围在using块的结尾,它的配置之后。更容易知道变量的相关位置,并且由于您不再需要powershell = null行,因此可以节省一些代码。我甚至会说这是更好的编码练习,因为powershell在已经处置的状态中从不存在。如果有人修改了您的原始代码并尝试在using块之外使用powershell,则不管发生什么情况都可能会导致问题。

+6

.NET运行时不要求您引用空值,并且一旦它们不再被引用(即通常在方法结束之前发生),它就会检测到符合收集条件的对象。 –

+0

@Justin Morgan Re模式看起来很奇怪,好吧,它会符合代码示例的质量的其余部分,然后我猜;-) – noonand

+0

@BrianRasmussen优秀的一点!这意味着这样做更没有用。 –

7

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

1

建议不正确,只要其无法访问,采集。 (见What is the correct way to free memory in C#一段代码演示这一点)的唯一原因,空出来的东西是

  • 为了更容易解决内存泄漏
  • 要删除引用(例如公共属性)的GC可能会遇到麻烦确定不可达

这两者你真的只是做一个对象中Dispose方法

相关问题