嵌套使用语句和微软代码分析

本文关键字:代码 微软 语句 嵌套 | 更新日期: 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 == trueXmlReaderSettings, XmlReader将处理TextReader,但是CA2202规则不够聪明,您的代码不会沿着该分支前进。保留您的嵌套用法,并将CA2202违规抑制为误报。

如果你想在你的代码中显式,以增强其可读性和/或可维护性,使用XmlReaderSettingsCloseInput设置为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
    }
}