最近我开启了其他代码分析规则。 令我惊讶的是,我在一个我一直在考虑作为最佳实践的地方看到了违规行为。 如果我有两个嵌套的一次性用品,我会使用两个这样的语句:
using (StringReader strReader = new StringReader(xmlString))
using (XmlReader xmlReader = XmlReader.Create(strReader))
{
result.ReadXml(xmlReader);
}
这也对应于高评级Q& A 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);
}
胡拉!警告消失了。但是,田田!新的一个发生了:
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 :(得分:21)
问题不在于嵌套使用。他们很好,一般建议。这里的问题是XmlReader
如果您使用TextReader
传递XmlReaderSettings
,则会处置CloseInput == true
,但CA2202规则不够智能,您的代码将无法运行那个分支。保持嵌套使用,并将CA2202违规视为误报。
如果您希望在代码中明确以提高其可读性和/或可维护性,请使用XmlReaderSettings
并将CloseInput
设置为false
,但这是默认值因此,这不是绝对必要的,而且,要明确,不会满足规则。
答案 1 :(得分: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
}
}