2013-10-10 65 views
3

在下面的代码中,我得到一个XmlNodeList作为返回值从XmlDocument.SelectNodes()我应该处理的XmlNodeList

foreach (XmlNode node in doc.SelectNodes(xPath)) 
{ 
    // Do stuff 
} 

事实证明,XmlNodeList实现IDisposable。这是否意味着每次我想迭代XmlDocument.SelectNodes()的返回值时,我都应该把它放在一个局部变量中,并确保它被丢弃(即将其置于using块中)?

像这样:

using(XmlNodeList nodes = doc.SelectNodes(xPath)) 
{ 
    foreach (XmlNode node in nodes) 
    { 
     // Do stuff 
    } 
} 
+0

看看这个:http://stackoverflow.com/questions/14398798/why-is-xmlnodelist-disposable – Chris

+0

@Chris:我看到了。虽然@AgentFire指出我应该调用Dispose()还是不全面,但我没有向我清楚,我明显应该这么做。它确实使'SelectNodes()'不太吸引人。 –

+0

我同意 - 不得不处置它并不好玩。就我个人而言,我想我会忘记我曾经阅读过这些,并继续像以前一样不加处理...... – Chris

回答

6

System.Xml命名空间是,呃,靠不住的。最好的方式,我可以把它。 XmlNodeList是一个抽象类,它继承了IDisposable并实现了一次性模式,但本身并不做任何事情。

有三个内部类派生自XmlNodeList。其中一个实际上覆盖了Dispose(bool)方法,XmlElementList。该类有一个类型为XmlElementListener的私有字段。而另一个内部班级,并不是那么明显,它似乎在“听”列出变化。 Dispose方法(等待它)取消订阅两个事件处理程序。

这打破了书中的每一条规则,它是从来没有正确的滥用IDisposable。不幸的是,你必须走散步,如果你不调用Dispose(),那么看看这个listener是否被实例化,以及这些事件处理程序是否会在你的程序中造成持久泄漏是几乎不可能的。你最好打电话给它。

许多令人敬畏的代码在.NET Framework中。好的代码总是需要糟糕的代码才能明显地看到好的代码有多好。这是System.Xml的工作。

+0

哪一部分“违反书中的每一条规则”?还是全部呢? – Andrew

+0

'IDisposable'旨在用于任何确定性的通用清理,而不仅仅用于处理非托管资源。微软在不久前改变了他们的观点。查看完全相同的使用模式的观察者模式。这不违反任何规则。 –

+0

我最好援引以下母语为英语的人:https://www.google.com/#q=eric+lippert+idisposable+abuse –