MemoryStream、XmlTextWriter 和警告 4 CA2202:Microsoft.Usage
Posted
技术标签:
【中文标题】MemoryStream、XmlTextWriter 和警告 4 CA2202:Microsoft.Usage【英文标题】:MemoryStream, XmlTextWriter and Warning 4 CA2202 : Microsoft.Usage 【发布时间】:2010-12-21 20:51:58 【问题描述】:Visual Studio 2010 Ultimate 中的运行代码分析命令在看到带有MemoryStream
和XmlTextWriter
的特定模式时会返回警告。
这是警告:
警告 7 CA2202:Microsoft.Usage: 对象 'ms' 可以被处理多个 一次方法 'KinteWritePages.GetXPathDocument(DbConnection)'。 为了避免产生 System.ObjectDisposedException 你 不应调用 Dispose 多个 对象上的时间。:行: 421 C:\Visual Studio 2010\Projects\Songhay.DataAccess.KinteWritePages\KinteWritePages.cs 421 Songhay.DataAccess.KinteWritePages
这是表格:
static XPathDocument GetXPathDocument(DbConnection connection)
XPathDocument xpDoc = null;
var ms = new MemoryStream();
try
using(XmlTextWriter writer = new XmlTextWriter(ms, Encoding.UTF8))
using(DbDataReader reader = CommonReader.GetReader(connection, Resources.KinteRssSql))
writer.WriteStartDocument();
writer.WriteStartElement("data");
do
while(reader.Read())
writer.WriteStartElement("item");
for(int i = 0; i < reader.FieldCount; i++)
writer.WriteRaw(String.Format("<0>1</0>", reader.GetName(i), reader[i].ToString()));
writer.WriteFullEndElement();
while(reader.NextResult());
writer.WriteFullEndElement();
writer.WriteEndDocument();
writer.Flush();
ms.Position = 0;
xpDoc = new XPathDocument(ms);
finally
ms.Dispose();
return xpDoc;
此表单会产生相同类型的警告:
XPathDocument xpDoc = null;
using(var ms = new MemoryStream())
using(XmlTextWriter writer = new XmlTextWriter(ms, Encoding.UTF8))
using(DbDataReader reader = CommonReader.GetReader(connection, Resources.KinteRssSql))
//...
return xpDoc;
顺便说一句,下面的表格会产生另一个警告:
XPathDocument xpDoc = null;
var ms = new MemoryStream();
using(XmlTextWriter writer = new XmlTextWriter(ms, Encoding.UTF8))
using(DbDataReader reader = CommonReader.GetReader(connection, Resources.KinteRssSql))
//...
return xpDoc;
以上产生警告:
警告 7 CA2000: Microsoft.Reliability:方法中 'KinteWritePages.GetXPathDocument(DbConnection)', 对象 'ms' 并未全部处置 异常路径。称呼 System.IDisposable.Dispose 对象 'ms' 在所有对它的引用之前 超出范围。 C:\Visual Studio 2010\Projects\Songhay.DataAccess.KinteWritePages\KinteWritePages.cs 383 Songhay.DataAccess.KinteWritePages
除了以下之外,我还有哪些选择?:
禁止警告 CA2202。 禁止警告 CA2000 并希望 微软正在处理MemoryStream
(因为
Reflector 没有向我显示源代码)。
重写我的旧代码以识别
精彩的XDocument
和 LINQ to
XML。
【问题讨论】:
C# CA2000:Dispose objects before losing scope using FileStream/XmlTextReader 的可能重复项 【参考方案1】:首先,你不应该使用new XmlTextWriter()
。自 .NET 2.0 以来,它已被弃用。请改用XmlWriter.Create()
。
其次,ms
的赋值应该在 using 块中:
using (var ms = new MemoryStream())
using (var writer = XmlWriter.Create(ms))
// ...
我相信警告是正确的。 MemoryStream
可以在 XmlTextWriter
被释放时被释放,然后在“finally
”块中再次被释放。
【讨论】:
这里需要注意的一点:在更高版本的 .Net Framework 中,XmlWriter.Create(stream) 创建了一个 XmlWriter.Settings.CloseOutput 为“假”的对象,您确实需要处理MemoryStream 分开。问题是 CA2202 仍然被引发,即使 Dispose() 只在底层流上被调用一次。我只是压制了警告并将其证明为误报。 @russell 这很有意义。如果您将现有流传递给它,则它属于您,并且您知道何时关闭它。【参考方案2】:如果这是我的代码库,我会禁止它。代码分析可以警告您潜在的问题,只要您(以及团队中的其他所有人,包括所有未来的开发人员)意识到潜在的问题,您就可以了。 Here's Microsoft's way 避免这个问题(在我看来,这违背了using()
的目的。
在类似的注释中,here's some code 向您展示了您可能如何实际遇到此修复的错误。第一个代码块写入MemoryStream
会关闭StreamWriter
,然后尝试在另一个StreamReader
中读取它。不幸的是,StreamWriter
上的Dispose()
也关闭了MemoryStream
。解决方案是从StreamWriter
中创建StreamReader
。
【讨论】:
以上是关于MemoryStream、XmlTextWriter 和警告 4 CA2202:Microsoft.Usage的主要内容,如果未能解决你的问题,请参考以下文章
为啥 MemoryStream.GetBuffer() 总是抛出?