2010-10-19 8 views
6

Wenn Sie über einige C# Code wie folgt mit verschachtelten mit Aussagen/Ressourcen kam:.NET - verschachtelt Ersetzen Aussagen mit einzelnen mit Anweisung using

using (var response = (HttpWebResponse)request.GetResponse()) 
{ 
    using (var responseStream = response.GetResponseStream()) 
    { 
     using (var reader = new BinaryReader(responseStream)) 
     { 
      // do something with reader 
     } 
    } 
} 

Ist es sicher, es mit etwas zu ersetzen?

using (var reader = new BinaryReader(((HttpWebResponse)request.GetResponse()).GetResponseStream())) 
{ 
    // do something with reader 
} 

Das obige Beispiel ist nur ein Beispiel für geschachtelte Einwegressourcen, also vergib mir, wenn es nicht genau die richtige Verwendung ist. Ich bin neugierig, wenn Sie die äußerste Ressource (den BinaryReader in diesem Fall) entsorgen, wenn sie rekursiv ihre untergeordneten Elemente für Sie abstellt oder wenn Sie jede "Schicht" explizit mit separaten using-Anweisungen entsorgen müssen? Z.B. Wenn Sie den BinaryReader entsorgt haben, soll er den Antwortstream entlasten, der wiederum die Antwort entbindet? Wenn ich über diesen letzten Satz nachdenke, denke ich, dass Sie die separaten using-Anweisungen brauchen, weil es keine Möglichkeit gibt, zu garantieren, dass ein Wrapper-Objekt über das innere Objekt verfügen würde. Ist das richtig?

Antwort

12

Sie benötigen die separaten Anweisungen verwenden.

In Ihrem zweiten Beispiel wird nur die BinaryReader entsorgt, nicht die Objekte, die verwendet wurden, um sie zu konstruieren.

Um zu sehen, warum, schauen Sie, was die using statement tatsächlich tut. Es dauert Ihren zweiten Code, und tut etwas Gleichwertiges zu:

{ 
    var reader = new BinaryReader(((HttpWebResponse)request.GetResponse()).GetResponseStream()); 
    try 
    { 
     // do something with reader 
    } 
    finally 
    { 
     if (reader != null) 
      ((IDisposable)reader).Dispose(); 
    } 
} 

Wie Sie sehen können, würde es nie ein Dispose() Anruf auf dem Response oder ResponseStream sein.

+0

Sie brauchen sie, aber ich glaube nicht, dass sie verschachtelt werden müssen. Ich denke, sie können einfach übereinander gestapelt werden. –

+0

@Matt: Ja, aber sie müssen alle drei existieren. –

+0

'BinaryReader.Close' schließt den zugrunde liegenden Stream. Und da 'Stream.Close' letztendlich' Stream.Dispose' aufruft, muss der Stream nach dem Schließen des Readers nicht geschlossen werden. Siehe http://msdn.microsoft.com/en-us/library/system.net.httpwebresponse.aspx und http://msdn.microsoft.com/en-us/library/system.io.stream.close.aspx . –

13

Sie sollten nur Ihre using-Anweisungen stapeln - es die gewünschte Wirkung hat, die Sie suchen:

using (var response = (HttpWebResponse)request.GetResponse()) 
using (var responseStream = response.GetResponseStream()) 
using (var reader = new BinaryReader(responseStream)) 
{ 
    // do something with reader 
} 
+0

Dies ist im Wesentlichen der gleiche Code mit unterschiedlicher Formatierung (nur die Klammern entfernen). –

+0

Wie verbessert dies die Dinge, das ist effektiv, was das OP hatte nur minus die geschweiften Klammern, die für die ersten beiden 'using' Anweisungen optional waren. – slugster

+0

Ja, es ist das gleiche, aber im Vergleich zu dem, was der Autor das Original ersetzen wollte, ist dies viel einfacher zu lesen und zu pflegen –

3

FWIW, hier ist eine andere Art und Weise Ihr ursprüngliches Beispiel zu buchstabieren, die jede Bestürzung über Verschachtelung erfüllen kann:

using (var response = (HttpWebResponse)request.GetResponse()) 
using (var responseStream = response.GetResponseStream()) 
using (var reader = new BinaryReader(responseStream)) 
{ 
    // do something with reader 
} 

Ob der Leser über den Stream verfügt ist wirklich eine Funktion des Lesers, nicht die "Verwendung". Soweit ich mich erinnere, ist das Verhalten der Leser oft - sie nehmen Besitz vom Strom und entsorgen ihn, wenn der Leser selbst geschlossen ist. Aber die Form, die ich oben zur Verfügung gestellt habe, sollte in Ordnung sein.

1

Gemäß der Dokumentation wird BinaryReader.Close den zugrunde liegenden Stream schließen. http://msdn.microsoft.com/en-us/library/system.io.binaryreader.close.aspx

Entsprechend der Dokumentation für HttpWebResponse müssen Sie entweder den zugrunde liegenden Stream schließen oder die Antwort entsorgen. http://msdn.microsoft.com/en-us/library/system.net.httpwebresponse.aspx

Also das zweite Beispiel, das Sie zur Verfügung gestellt haben, würde funktionieren.

+0

Danke für die Antwort ... Ich vermutete, dass es andere Möglichkeiten gab. Ich denke, im Zweifelsfall ist es am besten, alles zu schließen oder zu entsorgen, es sei denn, Sie wissen, was jeder Typ macht. –

0

Ich postete dies an anderer Stelle, aber Trennung Ihrer Deklarationen durch Komma scheint jede getrennte Anweisung auf diese Weise als eine neue Deklaration zu behandeln und entsorgt sie.

using (IType1 a = new Type1(), b = new Type1()){}

Dies aber bedeutet, dass Ihre Objekte vom gleichen Typ sein müssen.Man könnte sie wie

using (IDisposable a = new Type1(), b = new Type2()){}

nennen Aber dann natürlich Sie nur Zugriff auf IDisposable Methoden haben, ohne das Objekt zu werfen, die ein bisschen dumm ist. Anstatt also, ich glaube, Sie

using (var a = new Type1(), b = new Type2()){}

verwenden Dies scheint Sie zu geben, die richtig getippt Objektreferenzen ermöglicht Ihnen den Zugriff auf die richtige Methode des zugeordneten Typs, und verfügt über beide Objekte erstellt. Wenn jemand weiß, warum ich nicht recht habe, lass es mich wissen, denn das scheint für mich zu funktionieren? (Ich weiß, diese Frage ist wirklich alt n Zeug, aber es ist alles, was ich bei der Suche nach dieser Antwort finden konnte)

Verwandte Themen