2011-11-11 45 views
25

最近我打开了其他代码分析规则。 令我惊讶的是,我在一个我一直认为是最佳实践的地方看到了违规行为。 如果我有两个嵌套的一次性用品,我把两个using语句是这样的:使用语句和Microsoft代码进行嵌套分析

using (StringReader strReader = new StringReader(xmlString)) 
    using (XmlReader xmlReader = XmlReader.Create(strReader)) 
    { 
     result.ReadXml(xmlReader); 
    } 

这也相当于高额定Q &一个 Nested using statements in C#

我得到的违反下列规定:

Warning 18 CA2202 : Microsoft.Usage : Object 'strReader' can be disposed more 
than once in method '????'. To avoid generating a System.ObjectDisposedException 
you should not call Dispose more than one time on an object.: Lines: ?? 

我所做的是一个直观的尝试和错误,认为外流关闭也可能处置内部我快速修复我的代码是这样的:

using (XmlReader xmlReader = XmlReader.Create(new StringReader(xmlString))) 
    { 
     result.ReadXml(xmlReader); 
    } 

Hura!警告消失了。但是,田田!新一发生:

Warning 18 CA2000 : Microsoft.Reliability : In method '????????', object 
'new StringReader(xmlString)' is not disposed along all exception paths. Call 
System.IDisposable.Dispose on object 'new StringReader(xmlString)' before all 
references to it are out of scope. 

然后我发现了一个很丑陋的解决方案:

{ 
     StringReader strReader = null; 
     try 
     { 
      strReader = new StringReader(xmlString); 
      using (XmlReader xmlReader = XmlReader.Create(strReader)) 
      { 
       strReader = null; 
       result.ReadXml(xmlReader); 
      } 
     } 
     finally 
     { 
      if (strReader != null) strReader.Dispose(); 
     } 
    } 

作为最后一步(像每一个优秀的程序员)我看着帮助页面CA2202让我吃惊准确我提出的最后一个UGLY解决方案是为了解决这个问题?

尝试{}终于围绕使用杂乱的代码非常多!对我来说,嵌套使用更可读。

问:有没有更好的做事方式?我正在寻找一种可以直观理解的解决方案。每个看到最后一个片段的人都会对发生的事情充满好奇心。

在此先感谢您的答案。

+0

像您这样的问题在您的P.S.中有过。可能属于MetaStackoverflow。事实上,这个问题可能已经在那里被提出并回答了。 –

+0

通过使用(的XmlReader的XmlReader = XmlReader.Create(strReader))我尝试的方式也以下代码 '使用(StringReader strReader =新StringReader(的xmlString)) { strReader = NULL; result.ReadXml(xmlReader); }' } 导致编译错误错误无法分配给'strReader',因为它是'使用变量' –

回答

21

问题不在于嵌套使用。他们很好,一般推荐。这里的问题是XmlReader将处置TextReader如果您通过​​与CloseInput == true,但CA2202规则不够聪明,您的代码将不会沿着该分支。保持您的嵌套使用,并将CA2202违规视为误报。

如果你想明确在你的代码,以增强其可读性和/或维护,使用​​与CloseInput设置为false,但是这是默认值,所以它不是绝对必要的,并且,要明确,不会满足规则。

顺便说一句,对于各种流和阅读器类型,存在类似的CA2202问题场景。不幸的是,它们与这个并不完全相同,所以最好的情况处理可以根据导致问题的类型而有所不同。

+0

'xmlReaderSettings.CloseInput = false'不符合规则。抑制确实似乎是解决这个问题的唯一正确方法。 在'Dispose'实现中容忍双重处置似乎是一个好主意,因此像'XmlReader'这样的用户可能会安静地处理你,如果有人用'using'语句包装你的类,它会使BOOM! 感谢您的好解释。公认! –

+3

我并不是建议将CloseInput设置为false将满足规则,而是您可能希望在代码中明确表示,以增强其可读性和/或可维护性。至于容忍多处理,即使没有相应的FxCop规则,也有一个.NET设计指南。 –

0

我最近有一个类似的问题,但因为我使用的序列化器不得不适应它,因为我无法立即将stringWriter设置为null。此变通办法避免了所有CA警告:

StringWriter stringWriter = null; 
XmlWriter xmlWriter = null; 
string serializedValue = null; 

try 
{ 
    XmlSerializer xmlserializer = new XmlSerializer(typeof(T)); 
    stringWriter = new StringWriter(); 

    xmlWriter = XmlWriter.Create(stringWriter); 
    xmlserializer.Serialize(xmlWriter, value); 
    xmlWriter.Flush(); 
    serializedValue = stringWriter.ToString(); 
} 
finally 
{ 
    if (xmlWriter != null) //Both objects need disposed 
    { 
     xmlWriter.Dispose(); //stringWriter will dispose automatically too 
    } 
    else if (stringWriter != null) //XmlWriter failed to create 
    { 
     stringWriter.Dispose(); //just dispose stringWriter 
    } 
}