嵌套使用语句和微软代码分析
本文关键字:代码 微软 语句 嵌套 | 更新日期: 2023-09-27 18:14:06
最近我打开了额外的代码分析规则。令我惊讶的是,我在一个我一直认为是最佳实践的地方看到了违规行为。如果我有两个嵌套的disposable语句,我就像这样放两个using语句:
using (StringReader strReader = new StringReader(xmlString))
using (XmlReader xmlReader = XmlReader.Create(strReader))
{
result.ReadXml(xmlReader);
}
这也对应于高额定值Q&Ac#中的嵌套using语句
我得到的违例状态如下:
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的帮助页面,令我惊讶的是,我的最后一个丑陋解决方案被提议来解决这个问题?
最后使用try{}会使代码非常混乱!对我来说是嵌套使用可读性更强。
问题:有没有更好的做事方式?我正在寻找一个解决方案,这将是直观易懂的。每个看到这最后一个片段的人都会好奇到底发生了什么。提前感谢您的回答。
问题不在于嵌套用法。它们很好,通常被推荐使用。这里的问题是,如果您通过CloseInput == true
的XmlReaderSettings
, XmlReader
将处理TextReader
,但是CA2202规则不够聪明,您的代码不会沿着该分支前进。保留您的嵌套用法,并将CA2202违规抑制为误报。
如果你想在你的代码中显式,以增强其可读性和/或可维护性,使用XmlReaderSettings
和CloseInput
设置为false
,但这是默认值,所以它不是严格必要的,并且,要清楚,将不满足规则。
顺便说一句,对于各种流和阅读器类型都有类似的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
}
}