2009-08-07 6 views
11

Ich habe einen Code ähnlich wie diese haben:Stream.Dispose oder stream = null?

HttpWebRequest req; 
HttpWebResponse response; 
Stream receiveStream = null; 
StreamReader readStream = null; 
try 
{ 
    req = (HttpWebRequest)WebRequest.Create("someUrl")); 
    req.Credentials = CredentialCache.DefaultCredentials; 

    req.Method = "GET"; 

    response = (HttpWebResponse)req.GetResponse(); 
    receiveStream = response.GetResponseStream(); 
    readStream = new StreamReader(receiveStream, Encoding.Default); 

    return readStream.ReadToEnd(); 
} 
catch 
{ 
    return "Error"; 
} 
finally 
{ 
    readStream = null; 
    receiveStream = null; 
    response = null; 
    req = null; 
} 

Sollte dieser Code haben readStream.Dispose() und responseStream.Dispose() anstelle beide Einstellung auf null?

+1

+1 Froh, dass Sie diese Frage stellen! Die meisten kopierten und eingefügten Google-Codes ignorieren dies. – n8wrl

+3

Randnotiz, aber möglicherweise nicht relevant. Sie sollten keinen 'catch' all block haben. Das ist keine gute Übung. Sie möchten bestimmte Ausnahmen suchen, abfangen und behandeln. Andernfalls möchten Sie, dass sich die Ausnahme ausbreitet. Wenn du dir dessen schon bewusst bist, vergib mir. –

+0

Danke für alle Antworten. Ich fange an zu disponieren :-) Für den Rekord schneide ich die Ausnahmebehandlung aus dem Beispiel, also ist es nicht so schlecht, wie es scheint, obwohl ich von den Kommentaren denke, dass das etwas anderes ist, das verbessert werden kann. Danke nochmal alle – Temple

Antwort

28

Es ist fast immer ein Fehler, lokale Variablen auf null zu setzen, es sei denn, Sie tatsächlich später diesen Wert auf verwenden möchten. Die Speicherbereinigung wird nicht früher erzwungen. Wenn Sie später nicht von der Variablen lesen, kann der Speicherbereiniger die Referenz ignorieren (wenn nicht im Debug-Modus).

Es ist jedoch fast immer richtig, Streams zu schließen - idealerweise in einer using Anweisung der Einfachheit halber.

Es ist auch fast immer falsch, einen bloßen "fangen" Block so zu haben. Wollen Sie wirklich mit alles schief gehen, einschließlich Dinge wie OutOfMemoryException?

Ich würde neu schreiben Ihren Code wie:

HttpWebRequest req = (HttpWebRequest) WebRequest.Create("someUrl")); 
req.Credentials = CredentialCache.DefaultCredentials; 
req.Method = "GET"; 

using (WebResponse response = req.GetResponse()) 
{ 
    using (StreamReader reader = new StreamReader(response.GetResponseStream(), 
                Encoding.Default)) 
    { 
     return reader.ReadToEnd(); 
    } 
} 

Nun, wenn etwas schief geht, wird die Ausnahme an den Aufrufer propagiert werden. Vielleicht möchten Sie ein paar spezifische Ausnahmen fangen, aber es ist im Allgemeinen keine gute Idee, Fehler mit einem Wert darzustellen, der eine gültige "normale" Antwort hätte sein können.

Sind Sie wirklich sicher, dass Sie wollen Encoding.Default? Das ist die Standardcodierung des lokalen Computers - normalerweise möchten Sie die Codierung, die von der Antwort selbst angezeigt wird.

+4

Es gibt einen Grund, lokale Variablen auf null zu setzen: Sie warnen andere Entwickler, dass sie den Code dieser Person sehr sorgfältig überprüfen müssen. –

27

Es sollte using [die Dispose() ruft] haben.

2

Nein, sollten Sie Dispose aufrufen oder schließen

1

Ja - Sie sollten explizit Dispose() auf Klassen aufrufen, die IDisposable implementieren, nachdem Sie sie benutzt haben - dies stellt sicher, alle ihre Ressourcen erhalten in einer angemessenen Art und Weise gereinigt. Wickeln Sie die Variable in einem using() tut die gleiche Sache (die Code fügt Verpackung, die Entsorgung für Sie ruft):

using (StreamReader reader = new StreamReader()) { 
    // do stuff with reader 
} 
4

Ja.

Wenn Sie auf null setzen, wird nur die Referenz nullgestellt. Es wird kein Bereinigungscode ausgeführt, den der Ersteller der Stream-Klasse geschrieben hat.

Sie können auch die using(){ }-Anweisung, die dies für Sie auf IDisposable Typen behandelt behandeln.

Beispiel:

using (MyDisposableObject mdo = new MyDisposableObject) 
{ 
    // Do some stuff with mdo 
    // mdo will automatically get disposed by the using clause 
} 
8

Ja. Für so ziemlich alles, was eine Dispose() -Methode implementiert, muss die Dispose() -Methode aufgerufen werden. Sie können es implizit mit dem ‚mit‘ Aussage in einem Aufruf:

using(StreamReader stream = GetStream()) 
{ 
    stream.DoStuff(); 
} 
+0

Du verpasst den Variablennamen dort – thecoop

+1

Whoops. Fest. –

9

Ja, Dispose() sie.

Noch besser ist so etwas wie

using (HttpWebResponse response = (HttpWebResponse)req.GetResponse()) 
using (Stream receiveStream = response.GetResponseStream()) 
using (readStream = new StreamReader(receiveStream, Encoding.Default)) 
{ 
    return readStream.ReadToEnd(); 
} 

A using(x) {} Block neu geschrieben werden (durch den Compiler)
als try {} finally {x.Dispose();}

Hinweis zu tun, dass der WebRequest nicht IDisposable ist.

Beachten Sie auch, dass die folgenden Zeilen die gleiche Sache wie alle Ihre Code auszuführen:

using (var client = new System.Net.WebClient()) 
{ 
    client.Encoding = ...; 
    client.Credentials = ...; 
    return client.DownloadString("SomeUrl"); 
} 
0

ein paar Fallstricke in den .net-Bibliotheken Es gibt keine. Stream ist eins, und das andere ist ein Großteil der Imaging-API. Diese Entitäten, die bestimmte Systemressourcen verwenden, sammeln keine angehängten Systemressourcen.

Wenn die IDisposable-API verwendet wird, ist es am besten, sie in einen using-Block zu packen, wie oben erwähnt.

Lesen Sie auf "Verwendung" und denken Sie daran, wenn Sie mit Dateigriffen oder Bildern zu tun haben.

0

Wirklich, die Frage wurde beantwortet, aber ich möchte auf eine Sache näher eingehen.

Jedes Mal, wenn ein Objekt, das den IDisposable-Schnittstelle implementiert, sollten Sie es mit der Dispose-Methode entsorgen oder (noch besser) die using Aussage.

Wenn Sie jemals mit dieser Frage in der Zukunft konfrontiert werden, finden Sie einfach heraus, welche Schnittstellen es implementiert. Sobald Sie IDisposable sehen, wissen Sie, um es zu entsorgen.

2

Sicherste Methode:

try { 
    HttpWebRequest request = (HttpWebRequest) WebRequest.Create("someUrl"); 
    request.Credentials = CredentialCache.DefaultCredentials; 
    request.Method = "GET"; 
    using (HttpWebResponse response = (HttpWebResponse) request.GetResponse()) { 
     using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.Default)) { 
      return reader.ReadToEnd(); 
     } 
    } 
} catch { 
    return "Error"; 
} 

Es gibt keine Notwendigkeit des response.GetResponseStream() Strom ausdrücklich zu entsorgen, da das angeschlossene StreamReader es für Sie entsorgen wird.

EDIT: Ich stimme den anderen Antworten - Abfangen von Ausnahmen wie das ist sehr schlechte Praxis. Ich habe es nur zum Vergleich gelassen. :-)

0

Wenn Sie den Stream löschen müssen, verwenden Sie null; Ansonsten verwende das Dispose(); Methode, wenn Ihre Anwendung den Stream nicht mehr benötigt.

+0

Was bedeutet "clear the stream", und was hat das Setzen einer Variablenreferenz auf null damit zu tun? –

Verwandte Themen