2010-12-21 46 views
2

運行代碼分析在Visual Studio 2010 Ultimate中的命令在看到MemoryStreamXmlTextWriter的特定模式時返回警告。MemoryStream,XmlTextWriter和Warning 4 CA2202:Microsoft.Usage

這是警告:

警告7 CA2202:Microsoft.Usage: 對象 'MS' 可以設置在方法 'KinteWritePages.GetXPathDocument(的DbConnection)' 超過 一次。 爲了避免產生 System.ObjectDisposedException你 不應調用Dispose多個 時間:物體上線: 421 C:\的Visual Studio 2010 \項目\ 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 \項目\ Songhay.DataAccess.KinteWritePages \ KinteWritePages.cs 383 Songhay.DataAccess.KinteWritePages

除了下面,我有哪些選擇?:

  • 剿警告CA2202。
  • 剿警告CA2000和希望 微軟處置 MemoryStream(因爲 反射沒有顯示我的源代碼)。
  • 重寫我的遺留代碼以識別 精彩的XDocument和LINQ到 XML。
+0

[C#CA2000:使用FileStream/XmlTextReader丟失作用域前丟棄​​對象]的可能重複(http://stackoverflow.com/questions/3128446/c-ca2000dispose-objects-before-losing-scope-using-filestream-xmltextreader ) – 2010-12-21 21:59:07

回答

1

如果這是我的代碼庫,我會壓制它。代碼分析是爲了警告你潛在的問題,只要你(包括你所有團隊中的其他人,包括所有未來的開發人員)都知道你可能遇到的問題。 Here's Microsoft's way避免了這個問題(這在我看來打破了using()的目的。

在類似的說明中,here's some code向您展示瞭如何實際解決此問題。第一個代碼塊寫入MemoryStream會關閉StreamWriter,然後嘗試在另一個StreamReader中讀取它。不幸的是Dispose()StreamWriter也關閉了MemoryStream。解決方法是從StreamWriter內創建StreamReader

3

首先,你永遠不應該使用new XmlTextWriter()。從.NET 2.0開始已經被棄用了。改爲使用XmlWriter.Create()

其次,分配給ms應在使用塊:

using (var ms = new MemoryStream()) 
{ 
    using (var writer = XmlWriter.Create(ms)) 
    { 
     // ... 
    } 
} 

我相信警告是正確的。在處置XmlTextWriter時,可以放置MemoryStream,然後再放入「finally」塊中。