2011-11-11 18 views
25

Gần đây tôi đã bật các quy tắc phân tích mã bổ sung. Trước sự ngạc nhiên của tôi, tôi đã thấy một sự vi phạm ở một nơi mà tôi luôn xem là thực hành tốt nhất. Nếu tôi có hai lần hiện lồng nhau Tôi đặt hai sử dụng báo cáo như thế này:Báo cáo sử dụng lồng nhau và mã Microsoft Phân tích

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

này cũng tương ứng với đánh giá cao Q & Một Nested using statements in C#

Vi phạm tôi nhận được tình trạng sau:

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: ?? 

Những gì tôi đã làm là một thử trực quan và lỗi, nghĩ rằng gần của dòng bên ngoài cũng sẽ có thể vứt bỏ một bên trong tôi nhanh chóng sửa mã của tôi như thế này:

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

Hura! Cảnh báo đã biến mất. Nhưng, tada! Người mới xảy ra:

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. 

Sau đó, tôi tìm thấy một giải pháp rất xấu xí:

{ 
     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(); 
     } 
    } 

Là một bước cuối cùng (như mọi lập trình viên tốt) Tôi nhìn vào trang trợ giúp cho CA2202 và trước sự ngạc nhiên của tôi chính xác giải pháp UGLY cuối cùng của tôi đã được đề xuất để khắc phục vấn đề này?

Có cố gắng {} cuối cùng xung quanh bằng cách sử dụng cắt mã rất nhiều! Đối với tôi là lồng được sử dụng dễ đọc hơn nhiều.

Câu hỏi: Có cách nào tốt hơn để làm việc không? Tôi đang tìm một giải pháp mà sẽ trực giác dễ hiểu. Tất cả những người sẽ thấy đoạn trích cuối cùng này sẽ là những lời tò mò về những gì đang xảy ra.

Cảm ơn trước vì câu trả lời của bạn.

+0

Các câu hỏi như bạn đã có trong P.S. có thể thuộc về MetaStackoverflow. Trong thực tế, câu hỏi đó có thể đã được hỏi và trả lời ở đó. –

+0

Bằng cách này tôi đã cố gắng cũng mã sau 'sử dụng (StringReader strReader = new StringReader (xmlString)) sử dụng (XmlReader XmlReader = XmlReader.Create (strReader)) { strReader = null; kết quả.ReadXml (xmlReader); } ' dẫn đến lỗi biên dịch Lỗi Không thể gán cho 'strReader' vì nó là 'sử dụng biến' –

Trả lời

21

Vấn đề không phải do việc sử dụng lồng nhau. Chúng tốt và thường được đề nghị. Vấn đề ở đây là XmlReader sẽ xử lý TextReader nếu bạn vượt qua một số XmlReaderSettings với CloseInput == true, nhưng quy tắc CA2202 không đủ thông minh để mã của bạn không bị hỏng nhánh đó. Giữ cách sử dụng lồng nhau của bạn và ngăn chặn vi phạm CA2202 là dương tính giả.

Nếu bạn muốn rõ ràng trong mã của mình để tăng khả năng đọc và/hoặc khả năng bảo trì, hãy sử dụng XmlReaderSettings với CloseInput đặt thành false, nhưng đó là giá trị mặc định, vì vậy không cần thiết. rõ ràng, sẽ không thỏa mãn quy tắc.

BTW, có các trường hợp vấn đề CA2202 tương tự cho nhiều loại luồng và trình đọc khác nhau. Thật không may, họ không phải tất cả như thế này, vì vậy việc xử lý trường hợp tốt nhất có thể khác nhau tùy thuộc vào loại nào gây ra sự cố.

+0

' xmlReaderSettings.CloseInput = false' không thỏa mãn quy tắc. Sự đàn áp thực sự có vẻ là cách duy nhất để xử lý vấn đề này. Có vẻ như thường là một ý tưởng tốt để tha thứ cho việc xử lý hai lần trong 'Dispose', do đó một số người dùng như' XmlReader' có thể vứt bỏ bạn một cách im lặng và nếu ai đó kết thúc lớp của bạn trong câu lệnh 'using', nó tạo BOOM! Cảm ơn lời giải thích tuyệt vời. Đã chấp nhận! –

+3

Tôi đã không đề xuất rằng việc đặt CloseInput thành false sẽ đáp ứng quy tắc, nhưng thay vào đó bạn có thể muốn rõ ràng trong mã của mình để tăng cường khả năng đọc và/hoặc khả năng bảo trì của nó. Đối với việc chấp nhận xử lý nhiều lần, có một hướng dẫn thiết kế .NET cho điều này, ngay cả khi không có quy tắc FxCop tương ứng. –

0

Gần đây tôi đã có một vấn đề tương tự, nhưng khi tôi đang sử dụng bộ nối tiếp phải điều chỉnh nó vì tôi không thể đặt chuỗi ký tự thành null ngay lập tức. Cách giải quyết này tránh tất cả cảnh báo 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 
    } 
} 
Các vấn đề liên quan