2011-11-11 10 views
25

Ostatnio włączyłem dodatkowe zasady analizy kodu. Ku mojemu zaskoczeniu zobaczyłem naruszenie w miejscu, które zawsze uważałem za najlepszą praktykę. Jeśli mam dwie zagnieżdżone jednorazowych kładę dwa użyciu instrukcji tak:Zagnieżdżone przy użyciu instrukcji i analiz Microsoft Code

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

ten odpowiada również wysokiej znamionowej Q & A Nested using statements in C#

naruszenie dostaję stany następujące:

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

To, co zrobiłem, to intuicyjna próba i błąd, myśląc, że zamknięcie zewnętrznego strumienia prawdopodobnie również pozbędzie się wewnętrznego Szybko naprawiłem mój kod w ten sposób:

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

Hura! Ostrzeżenie znikło. Ale, tada! Nowa jeden wystąpiły:

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. 

Potem znalazłem bardzo brzydki rozwiązanie:

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

W ostatnim kroku (jak każdy dobry programista) zajrzałem do strony pomocy dla CA2202 i dokładnie mojego zaskoczenia moje ostatnie rozwiązanie UGLY zostało zaproponowane w celu rozwiązania problemu?

Posiadanie try {} w końcu przy użyciu zaśmieca kod bardzo! Dla mnie jest zagnieżdżony przy użyciu znacznie bardziej czytelny.

Pytanie: Czy istnieje lepszy sposób robienia rzeczy? Szukam rozwiązania, które będzie intuicyjnie zrozumiałe. Każdy, kto zobaczy ten ostatni fragment, będzie ciekawostką tego, co się dzieje.

Z góry dziękuję za odpowiedzi.

+0

Pytania takie jak w przypadku P.S. prawdopodobnie należą do MetaStackoverflow. W rzeczywistości to pytanie mogło już zostać zadane i tam udzielono odpowiedzi. –

+0

przez 'stosując (StringReader strReader = nowy StringReader (xmlString)) sposób, że próbuje również następnego kodu stosując (XmlReader XMLReader = XmlReader.Create (strReader)) { strReader = NULL; result.ReadXml (xmlReader); } ' prowadzi do kompilacji error nie można przypisać do 'strReader', ponieważ jest to 'za pomocą zmiennej' –

Odpowiedz

21

Problem nie wynika z zagnieżdżonych zastosowań. Są w porządku i ogólnie polecane. Problem polega na tym, że XmlReader pozbędzie się TextReader, jeśli przekażemy XmlReaderSettings z CloseInput == true, ale reguła CA2202 nie jest wystarczająco inteligentna, aby twój kod nie przeszedł w dół tej gałęzi. Zachowaj swoje zagnieżdżone funkcje i pomiń naruszenie CA2202 jako fałszywe pozytywne.

Jeśli chcesz być jawne w kodzie w celu zwiększenia jego czytelności i/lub konserwacji, należy użyć XmlReaderSettings z CloseInput zestaw do false, ale jest to wartość domyślna, więc nie jest to bezwzględnie konieczne, i, być jasne, nie spełniałoby reguły.

BTW, istnieją podobne scenariusze problemów CA2202 dla różnych typów strumienia i czytnika. Niestety, nie są one takie same, więc najlepsza obsługa może się różnić w zależności od typu problemu.

+0

' xmlReaderSettings.CloseInput = FALSE nie spełnia regułę. Tłumienie wydaje się być jedynym właściwym sposobem radzenia sobie z tym problemem. Wydaje się, że dobrym pomysłem jest tolerowanie podwójnego usuwania w implementacjach 'Dispose', więc niektórzy użytkownicy, tacy jak' XmlReader' mogą Cię pozbyć po cichu, a jeśli ktoś opakuje twoją klasę w instrukcję 'using', to BOOM! Dzięki za świetne wyjaśnienie. Przyjęty! –

+3

Nie sugerowałem, że ustawienie CloseInput na wartość false spełniłoby tę regułę, ale raczej chciałoby być wyraźne w kodzie, aby zwiększyć czytelność i/lub łatwość obsługi. Jeśli chodzi o tolerowanie wielokrotnego usuwania, istnieje wytyczna dotycząca projektowania .NET, nawet jeśli nie ma odpowiedniej reguły FxCop. –

0

Niedawno miałem podobny problem, ale ponieważ korzystałem z serializera, musiałem go zaadaptować, ponieważ nie byłem w stanie natychmiast ustawić wartości StringWriter na wartość null. To obejście pozwala uniknąć wszystkich ostrzeżeń CA:

Powiązane problemy