如何修复 CA2202 警告
本文关键字:警告 CA2202 何修复 | 更新日期: 2023-09-27 18:21:26
下面是我用来解析XML的方法。它给出了关于代码分析的 CA2202 警告,该警告说对象 mStream 可以多次释放,我不应该多次调用 dispose。如何解决此警告?
public static String PrintXML(String XML)
{
String result = "";
string[] xmlSeperators = new string[] { "<?" };
string[] splitResults = new string[2];
if (!String.IsNullOrEmpty(XML))
{
using (MemoryStream mStream = new MemoryStream())
{
using (XmlTextWriter writer = new XmlTextWriter(mStream, Encoding.Unicode))
{
XmlDocument document = new XmlDocument();
try
{
// Load the XmlDocument with the XML.
//Check if it is only XML
if (XML.StartsWith("<?"))
{
document.LoadXml(XML);
}
else
{
//Split the string appended before XML
splitResults = XML.Split(xmlSeperators, 2, StringSplitOptions.None);
if (splitResults.Length > 1)
{
string d = "<?" + splitResults[1];
document.LoadXml(d);
}
}
writer.Formatting = Formatting.Indented;
// Write the XML into a formatting XmlTextWriter
document.WriteContentTo(writer);
//xx.WriteTo(writer);
writer.Flush();
mStream.Flush();
// Have to rewind the MemoryStream in order to read its contents.
mStream.Position = 0;
// Read MemoryStream contents into a StreamReader.
StreamReader sReader = new StreamReader(mStream);
// Extract the text from the StreamReader.
String FormattedXML = sReader.ReadToEnd();
if (splitResults[0] != null)
{
result = splitResults[0] + "'n" + FormattedXML;
}
else
{
result = FormattedXML;
}
}
catch (XmlException xe)
{
Log.Error(xe);
throw;
}
}
}
}
return result;
}
收到此警告的原因是XmlTextWriter.Dispose()
将确保下躺的MemoryStream
对象也被释放。因此,当MemoryStream
的using
范围结束时,它将尝试释放MemoryStream
对象,从而释放警告。
using
块编译为try-finally
块。代码中的内部using
块将在writer
上调用Dispose
。这将调用MemoryStream
对象mStream
上的Dispose
。在从内部 using 块退出控件时,外部 using 块将尝试释放对象writer
,但由于它已被释放,因此在代码分析工具上收到警告。
要消除警告,您可以删除第一个using
语句并使用try-finally
块。但请记住,在输入第二个using
语句后立即将mStream
设置为null
。CA2202 中对此进行了解释:不要多次释放对象
您的代码如下所示:
public static String PrintXML(String XML)
{
String result = "";
string[] xmlSeperators = new string[] { "<?" };
string[] splitResults = new string[2];
if (!String.IsNullOrEmpty(XML))
{
MemoryStream mStream = null;
try
{
mStream = new MemoryStream();
using (XmlTextWriter writer = new XmlTextWriter(mStream, Encoding.Unicode))
{
mStream = null; // important
XmlDocument document = new XmlDocument();
try
{
// Load the XmlDocument with the XML.
//Check if it is only XML
if (XML.StartsWith("<?"))
{
document.LoadXml(XML);
}
else
{
//Split the string appended before XML
splitResults = XML.Split(xmlSeperators, 2, StringSplitOptions.None);
if (splitResults.Length > 1)
{
string d = "<?" + splitResults[1];
document.LoadXml(d);
}
}
writer.Formatting = System.Xml.Formatting.Indented;
// Write the XML into a formatting XmlTextWriter
document.WriteContentTo(writer);
//xx.WriteTo(writer);
writer.Flush();
mStream.Flush();
// Have to rewind the MemoryStream in order to read its contents.
mStream.Position = 0;
// Read MemoryStream contents into a StreamReader.
StreamReader sReader = new StreamReader(mStream);
// Extract the text from the StreamReader.
String FormattedXML = sReader.ReadToEnd();
if (splitResults[0] != null)
{
result = splitResults[0] + "'n" + FormattedXML;
}
else
{
result = FormattedXML;
}
}
catch (XmlException xe)
{
Log.Error(xe);
throw;
}
}
}
finally
{
if (mStream != null)
{
mStream.Dispose();
}
}
}
return result;
}
您可以像另一个答案所说的那样抑制错误警告,但消除此问题的实际方法是仅在代码中实际调用一次 .Dispose()
方法,并且仅在完成使用它之后调用它。如果再次释放已释放的对象,则会引发 System.ObjectDisposedException 异常,但不确定。可以在对象上多次调用正确的 dispose 方法,并且不会/可能不会为您生成错误。但不能保证这样做。
Microsoft的开发人员网络文档已对此进行了说明,
若要解决与此规则的冲突,请更改实现,以便无论代码路径如何,都只对对象调用一次 Dispose。
更多: http://msdn.microsoft.com/en-us/library/ms182334.aspx
当您嵌套了using
语句,其中内部语句包含外部语句中的资源时,会发生这种情况。在这种情况下,XmlTextWriter
将在处置MemoryStream
时对其进行处置,然后外部using
语句将导致第二次处置它。
您可以通过将外部using
语句替换为 try/finally 来手动释放内存流:
MemoryStream mStream = null;
try
{
mStream = new MemoryStream();
using (XmlTextWriter writer = new XmlTextWriter(mStream, Encoding.Unicode))
{
mStream = null;
...
}
}
finally
{
if(mStream != null)
mStream.Dispose();
}
(见 http://msdn.microsoft.com/en-us/library/ms182334.aspx(