2010-02-11 6 views
11

Muss ich dies tun, um sicherzustellen, dass der MemoryStream ordnungsgemäß entsorgt wird?Kann ich eine Variable "inline" einfügen, wenn sie IDisposible ist?

oder ist es in Ordnung, den MemoryStream so einzubinden, dass er einfach nicht mehr funktioniert? So was?

using (XmlReader reader = XmlReader.Create(new MemoryStream(bytes))) 
    { 
    return new XmlDocument().Load(reader); 
    } 
+0

Es hängt alles davon ab, wie in diesem Fall XmlReader.Dispose implementiert ist. – Will

+0

Vielen Dank sehr gut ;-) –

Antwort

10

Der XmlReader nimmt nicht standardmäßig (aber siehe Colins und dh Vorschlag) an, dass es der einzige ist, der einen Stream verwendet, also ist die erste Option die einzige sichere Dispose.

+0

Es sei denn, Sie verwenden XmlReaderSettings.CloseInput Eigenschaft, wie DH schlägt – Colin

3

Dies hängt wirklich von der Dispose() von XmlReader. Es würde etwas Arbeit brauchen, um genau herauszufinden, was es tut. Ich selbst schreibe Code wie die erste Probe. Wenn Sie etwas Neues, dann ist es Ihre Verantwortung, es zu entsorgen. Sie sollten nicht erwarten, dass andere sich um Sie kümmern (auch wenn sie es mögen).

+0

Danke Bryan, Ich auch. Ich frage mich nur, ob eine inline deklarierte Instanz immer als Teil des enthaltenden IDisposible betrachtet werden kann und somit immer entsorgt wird, wenn die dispose-Methode des Containers aufgerufen wird. Ich würde eine allgemeine Regel, die für alle IDisposibles obwohl wollte, möchte ich nicht es für einige und eine andere Weise für andere schreiben. – Colin

+2

Sie scheinen zu denken, dass "inline" wie in "in einem using block" etwas ist, das dem Code bekannt ist. Es ist nicht. using() {} ist nur syntaktischer Zucker für try {} finally {} und stellt sicher, dass .Dispose() aufgerufen wird. –

11

Als allgemeine Regel, ja, sollten Sie den Code wie im ersten Beispiel schreiben.

Es gibt einige Klassen, die den Besitz des an sie übergebenen Objekts übernehmen. Wenn Sie also das äußere Objekt ablegen, wird automatisch das innere Objekt für Sie entfernt, aber das ist die Ausnahme von der Regel.

In jedem Fall sollte der Aufruf von Dispose mehr als einmal sicher sein. Das heißt, Objekte sollten das so implementieren, dass es sicher ist und nur die Arbeit beim ersten Mal erledigt.

Also, als eine allgemeine Regel, gehen Sie mit der ersten Syntax.

Jetzt, für das angegebene Beispiel, sollte es nicht wirklich wichtig sein, wie ein MemoryStream nicht wirklich an Ressourcen hält, die entsorgt werden müssen, aber es gibt ein Problem mit dieser Erwartung auch. Wenn Sie wissen, dass eine bestimmte Version eines Objekts keine Ressource verwendet, können Sie die Dispose ignorieren. Wenn dieses Objekt in Zukunft eine solche Ressource erhält, erhalten Sie plötzlich ein Leck.

Es sei denn, Sie sehen eine nachteilige Wirkung mit dem gegebenen Code, wie das Hinzufügen von zu viel Overhead, dann würde ich mich einfach nicht darum kümmern.

+0

Ich mag die "einfach nicht sorgen" - wir sollen in der Lage sein, (meist) Speicherverwaltung zu vergessen, nicht wahr? Manchmal fühlt es sich so an, als hätten wir das Problem einfach umgepackt: * IDisposable * ... –

+4

'IDisposable' geht es nicht um Speicherverwaltung. Es geht um _resource_management. GC befreit Sie nicht davon, sich um die Ressourcenverwaltung zu sorgen. –

+0

Ich stimme beiden Kommentaren in gewissem Maße zu: Ja, es geht um * Ressourcen * Management, und 'IDisposable' gibt uns bei richtiger Anwendung das Gefühl, dass wir uns darüber keine Sorgen machen *. "IDisposable" ist, wenn es richtig und effizient verwendet wird, einfach ein Hilfsmittel, um den GC zu unterstützen, ohne seine angenommene Effizienz ernsthaft zu beeinträchtigen. IMO, wie kann alles, was als unbestimmt * beschrieben beschrieben wird, wirklich effizient sein? – IAbstract

2

Sie sprechen über zwei verschiedene Dinge:

  1. Aus gestalterischer Sicht eine Best-Practices, sollten Sie immer ein Objekt verfügen, für die Sie verantwortlich sind? Ja
  2. Werden Sie ein Speicherleck nach dem im zweiten Beispiel gezeigten Muster feststellen? Nein, wenn aus keinem anderen Grund als der Tatsache, dass MemoryStream.Dispose nicht tatsächlich irgendetwas tun.
4

Es gibt eine Option XmlReaderSettings zu verwenden und auf true closeinput wie diese

var reader = XmlReader.Create(new MemoryStream(), new XmlReaderSettings {CloseInput = true}); 

hier: XmlReaderSettings.CloseInput Property

-1

Speicherströme erfordern nicht wirklich Dispose() aufrufen. Die Frage ist jedoch immer noch gültig, da andere Arten von Streams Dispose() benötigen.

Verwandte Themen