2011-11-11 24 views
25

最近我打開了其他代碼分析規則。 令我驚訝的是,我在一個我一直認爲是最佳實踐的地方看到了違規行爲。 如果我有兩個嵌套的一次性用品,我把兩個using語句是這樣的:使用語句和Microsoft代碼進行嵌套分析

using (StringReader strReader = new StringReader(xmlString)) 
    using (XmlReader xmlReader = XmlReader.Create(strReader)) 
    { 
     result.ReadXml(xmlReader); 
    } 

這也相當於高額定Q &一個 Nested using statements in C#

我得到的違反下列規定:

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讓我吃驚準確我提出的最後一個UGLY解決方案是爲了解決這個問題?

嘗試{}終於圍繞使用雜亂的代碼非常多!對我來說,嵌套使用更可讀。

問:有沒有更好的做事方式?我正在尋找一種可以直觀理解的解決方案。每個看到最後一個片段的人都會對發生的事情充滿好奇心。

在此先感謝您的答案。

+0

像您這樣的問題在您的P.S.中有過。可能屬於MetaStackoverflow。事實上,這個問題可能已經在那裏被提出並回答了。 –

+0

通過使用(的XmlReader的XmlReader = XmlReader.Create(strReader))我嘗試的方式也以下代碼 '使用(StringReader strReader =新StringReader(的xmlString)) { strReader = NULL; result.ReadXml(xmlReader); }' } 導致編譯錯誤錯誤無法分配給'strReader',因爲它是'使用變量' –

回答

21

問題不在於嵌套使用。他們很好,一般推薦。這裏的問題是XmlReader將處置TextReader如果您通過​​與CloseInput == true,但CA2202規則不夠聰明,您的代碼將不會沿着該分支。保持您的嵌套使用,並將CA2202違規視爲誤報。

如果你想明確在你的代碼,以增強其可讀性和/或維護,使用​​與CloseInput設置爲false,但是這是默認值,所以它不是絕對必要的,並且,要明確,不會滿足規則。

順便說一句,對於各種流和閱讀器類型,存在類似的CA2202問題場景。不幸的是,它們與這個並不完全相同,所以最好的情況處理可以根據導致問題的類型而有所不同。

+0

'xmlReaderSettings.CloseInput = false'不符合規則。抑制確實似乎是解決這個問題的唯一正確方法。 在'Dispose'實現中容忍雙重處置似乎是一個好主意,因此像'XmlReader'這樣的用戶可能會安靜地處理你,如果有人用'using'語句包裝你的類,它會使BOOM! 感謝您的好解釋。公認! –

+3

我並不是建議將CloseInput設置爲false將滿足規則,而是您可能希望在代碼中明確表示,以增強其可讀性和/或可維護性。至於容忍多處理,即使沒有相應的FxCop規則,也有一個.NET設計指南。 –

0

我最近有一個類似的問題,但因爲我使用的序列化器不得不適應它,因爲我無法立即將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 
    } 
}