嵌套使用语句和Microsoft代码分析

最近我开启了额外的代码分析规则。 令我惊讶的是,我在一个我一直在考虑作为最佳实践的地方看到了违规行为。 如果我有两个嵌套的一次性用品,我会使用两个这样的语句:

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

这也对应于C#中高评级的Q&A 嵌套使用语句

我得到的违规行为如下:

 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); } 

胡拉! 警告消失了。 但是,田田! 新的一个发生:

 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解决方案来解决这个问题?

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

问题:有更好的做事方式吗? 我正在寻找一种直观易懂的解决方案。 每个看到最后片段的人都会对所发生的事情感到好奇。

提前感谢您的回答。

问题不在于嵌套使用。 他们很好,一般建议。 这里的问题是,如果你传递一个带有CloseInput == trueXmlReaderSettingsXmlReader将处理TextReader ,但是CA2202规则不够智能,你的代码不会下去那个分支。 保持嵌套使用,并将CA2202违规视为误报。

如果您希望在代码中明确以增强其可读性和/或可维护性,请使用将CloseInput设置为falseXmlReaderSettings ,但这是默认值,因此它不是绝对必要的,并且,要清楚,不会满足规则。

顺便说一句,对于各种流和阅读器类型,存在类似的CA2202问题场景。 不幸的是,它们并不完全相同,所以最好的案例处理可能会有所不同,具体取决于导致问题的类型。

我最近有类似的问题,但因为我使用序列化程序必须调整它,因为我无法立即将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 } }