webentwicklung-frage-antwort-db.com.de

MemoryStream.Close () oder MemoryStream.Dispose ()

Welches rufe ich an?

Müssen Sie beide anrufen?

Wird der andere eine Ausnahme auslösen, wenn ich bereits einen von ihnen angerufen habe?

47
ashwnacharya

Close() und Dispose() dienen bei Aufruf einer MemoryStream nur zu zwei Zwecken:

  • Markieren Sie das Objekt als entsorgt, damit bei versehentlicher Verwendung des Objekts eine Ausnahme ausgelöst wird.
  • Möglicherweise1 Geben Sie Verweise auf verwaltete Objekte frei, was die Arbeit des GC je nach GC-Implementierung etwas einfacher machen kann. (Bei den heutigen GC-Algorithmen macht es keinen wirklichen Unterschied, daher ist dies ein Punkt für eine akademische Diskussion und hat keine nennenswerten Auswirkungen auf die Realität.)

MemoryStream verfügt über keine nicht verwalteten Ressourcen, die Sie nicht zur Verfügung haben müssen, so dass Sie technisch nicht darüber verfügen müssen. Das Fehlen einer MemoryStream hat in etwa die gleiche Wirkung, als wenn Sie einen Verweis auf einen byte[] löschen - der GC wird beide auf dieselbe Weise bereinigen.

Welches rufe ich an? Müssen Sie beide anrufen?

Die Dispose()-Methode von Streams direkt an die Close()-Methode delegieren2, also machen beide genau dasselbe.

Wird der andere eine Ausnahme auslösen, wenn ich bereits einen von ihnen angerufen habe?

Die Dokumentation für IDisposable.Dispose() besagt ausdrücklich, dass es sicher ist, Dispose() für jedes Objekt mehrmals aufzurufen3. (Wenn dies für eine bestimmte Klasse nicht zutrifft, implementiert diese Klasse die IDisposable-Schnittstelle in einer Weise, die ihren Vertrag verletzt, und dies wäre ein Fehler.)

All dies zu sagen: Es macht wirklich keinen großen Unterschied, ob Sie eine MemoryStream haben oder nicht. Der einzige wirkliche Grund, warum es CloseDispose-Methoden gibt, ist, dass sie von Stream erbt. Dies erfordert, dass diese Methoden als Teil ihres Vertrages Streams unterstützen, die _/do über nicht verwaltete Ressourcen (wie Datei- oder Socket-Deskriptoren) verfügen.


1 Monos Implementierung gibt die byte[]-Referenz nicht frei. Ich weiß nicht, ob die Microsoft-Implementierung dies tut.

2 "Diese Methode ruft Close auf und ruft dann Stream.Dispose (Boolean) auf."

3 "Wenn die Dispose-Methode eines Objekts mehrmals aufgerufen wird, muss das Objekt alle Aufrufe nach dem ersten ignorieren."

92
cdhowie

Verwenden Sie den using-Block, damit Ihr Objekt verworfen wird, wenn dessen IDisposable-Schnittstelle implementiert ist

7
TalentTuner

Sie können dazu den using-Block verwenden. Es ruft automatisch Dispose auf, wenn es seinen Bereich verlässt.

Beispiel:

using (MemoryStream ms = new MemoryStream())
{
    // Do something with ms..
}
// ms is disposed here

Hoffe das hat geholfen.

6
Kevin

der folgende Code ist Stream.Dispose aus Reflektor. Wie Sie sehen können, müssen Sie nicht schließen, wenn Sie die Daten löschen.

public void Dispose()
{
    this.Close();
}
4
vc 74

Welches rufe ich an?

Jeder von ihnen.

Müssen Sie beide anrufen?

Nein, beides ist ausreichend.

Wird der andere eine Ausnahme auslösen, wenn ich bereits einen von ihnen angerufen habe?

Nein, das Einwegmuster gibt an, dass nachfolgende Aufrufe von Dispose keine negativen Auswirkungen haben.

4
QrystaL

Beim Aufruf von Close () wird intern Dispose () aufgerufen, um die Ressourcen freizugeben.

Siehe diesen Link für weitere Informationen: msdn

3
Hps

Aufruf nur Dispose() macht den Trick =)

1
Singleton

In .NET 3.5 (andere Versionen nicht geprüft) werden Methoden beim Disponieren eines MemoryStream in der folgenden Reihenfolge aufgerufen:

  1. Stream.Dispose ()
    • ruft einfach Schließen an
  2. Stream.Close ()
    • ruft Dispose (true) auf, dann GC.SuppressFinalize (this)
  3. MemoryStream.Dispose (true)
    • setzt die Flags _isOpen, _writable und _expandable auf false
  4. Stream.Dispose (true)
    • schließt ein asynchrones Ereignis, falls aktiv
1
Tor Langlo

Als erste Lösung wird empfohlen, möglichst Anweisungen zu verwenden. Dies wird hier beschrieben: http://msdn.Microsoft.com/en-us/library/yh598w02.aspx

Wenn die Lebensdauer eines IDisposable-Objekts auf eine einzelne Methode beschränkt ist, sollten Sie es in der using-Anweisung deklarieren und instanziieren. Die using-Anweisung ruft die Dispose-Methode für das Objekt auf die richtige Art und Weise auf, und (wenn Sie sie wie oben gezeigt verwenden), bewirkt auch das Objekt selbst, sobald der Dispose-Aufruf aufgerufen wird. Within Im Verwendungsblock ist das Objekt schreibgeschützt und kann nicht geändert oder neu zugewiesen werden.

Kommen wir jetzt zu der Frage: Wie in den meisten .NET-Framework-Klassen vorgeschlagen, gibt es keinen Unterschied zwischen Close () und Dispose (), und es ist egal, welche der beiden Methoden Sie aufrufen. Sie sollten eine anrufen, aber nicht beide. Es gibt Ausnahmen.

Es gibt Ausnahmen; Zum Beispiel verhalten sich System.Windows.Forms.Form und System.Data.SqlClient.SqlConnection bei Close () und Dispose () unterschiedlich.

Für vollständige Details können Sie hier nachschauen: https://blogs.msdn.Microsoft.com/kimhamil/2008/03/15/the-often-non-difference-zwischenclose-und-dispose/

0
sin2akshay

Nichts des oben Genannten. Sie müssen weder Close noch Dispose aufrufen.

MemoryStream enthält keine nicht verwalteten Ressourcen. Die einzige Ressource, die zurückgefordert werden soll, ist der Arbeitsspeicher. Der Speicher wird während der Speicherbereinigung mit dem Rest des Objekts MemoryStream zurückgefordert, wenn der Code nicht mehr auf die Variable MemoryStream verweist.

Wenn Sie einen langlebigen Verweis auf die Variable MemoryStream haben, können Sie diesen Verweis auf null setzen, um zu ermöglichen, dass die Variable MemoryStream Garbage gesammelt wird. Close und Dispose geben weder den eigentlichen Steam-Puffer noch das MemoryStream-Objekt frei.

Da weder Stream noch MemoryStream über einen Finalizer verfügen, müssen Sie Close oder Dispose nicht aufrufen, damit GC.SuppressFinalize aufgerufen wird, um die Garbage Collection zu optimieren. Es gibt keinen Finalizer zum Unterdrücken.

Die Dokumente für MemoryStream setzen es so:

Dieser Typ implementiert die IDisposable-Schnittstelle, verfügt jedoch nicht über tatsächlich verfügbare Ressourcen. Das bedeutet, dass die Entsorgung durch direktes Aufrufen von Dispose() oder durch Verwendung eines Sprachkonstrukts wie using (in C #) oder Using (in Visual Basic) nicht erforderlich ist.

0
Edward Brey