Welches rufe ich an?
Ist es notwendig, beide anzurufen?
Wird der andere eine Ausnahme auslösen, wenn ich bereits einen von ihnen angerufen habe?
Welches rufe ich an?
Ist es notwendig, beide anzurufen?
Wird der andere eine Ausnahme auslösen, wenn ich bereits einen von ihnen angerufen habe?
Antworten:
Close()
und Dispose()
wenn man dazu aufgefordert wird MemoryStream
, dient man nur dazu, zwei Dinge zu tun:
MemoryStream
Es stehen keine nicht verwalteten Ressourcen zur Verfügung, sodass Sie diese technisch nicht entsorgen müssen. Der Effekt, a nicht zu entsorgen, MemoryStream
ist ungefähr der gleiche wie das Löschen eines Verweises auf a byte[]
- der GC bereinigt beide auf die gleiche Weise.
Welches rufe ich an? Ist es notwendig, beide anzurufen?
Die Dispose()
Methode der Streams wird direkt an die Close()
Methode 2 delegiert , sodass beide genau dasselbe tun.
Wird der andere eine Ausnahme auslösen, wenn ich bereits einen von ihnen angerufen habe?
In der Dokumentation wirdIDisposable.Dispose()
ausdrücklich angegeben, dass es sicher ist Dispose()
, jedes Objekt 3 mehrmals aufzurufen . (Wenn dies für eine bestimmte Klasse nicht zutrifft, implementiert diese Klasse die IDisposable
Schnittstelle auf eine Weise, die gegen ihren Vertrag verstößt, und dies wäre ein Fehler.)
Das alles zu sagen: Es macht wirklich keinen großen Unterschied, ob Sie einen entsorgen MemoryStream
oder nicht. Der einzige wirkliche Grund, warum es Close
/ Dispose
Methoden hat, ist, dass es von erbt Stream
, was erfordert, dass diese Methoden als Teil seines Vertrags Streams unterstützen, die nicht verwaltete Ressourcen haben (wie Datei- oder Socket-Deskriptoren).
1 Die Implementierung von Mono gibt die byte[]
Referenz nicht frei . Ich weiß nicht, ob die Microsoft-Implementierung dies tut.
2 "Diese Methode ruft Close auf, das dann Stream.Dispose (Boolean) aufruft."
3 "Wenn die Dispose-Methode eines Objekts mehrmals aufgerufen wird, muss das Objekt alle Aufrufe nach dem ersten ignorieren."
MemoryStream
, der die Arbeit des GC erleichtert, nur gilt, wenn Sie aus irgendeinem Grund einen Verweis auf das entsorgte Stream-Objekt hatten.
1
gibt laut .NET-Referenzquelle .Dispose()
auch die interne byte[]
nicht frei. Die einzige Ressource, die festgelegt null
wird _lastReadTask
, wird nur in der Methode verwendet Task<int> ReadAsync(byte[], int, int, CancellationToken)
. Neben Einstellung , dass eine Variable null alle ist es gesetzt _isOpen
, _writable
und _expandable
zu false
.
Nichts des oben Genannten. Sie müssen weder anrufen Close
noch Dispose
.
MemoryStream
enthält keine nicht verwalteten Ressourcen, daher ist die einzige Ressource, die zurückgefordert werden kann, Speicher. Der Speicher wird während der Speicherbereinigung mit dem Rest des MemoryStream
Objekts zurückgefordert, wenn Ihr Code nicht mehr auf das verweist MemoryStream
.
Wenn Sie einen langlebigen Verweis auf das haben MemoryStream
, können Sie diesen Verweis auf null setzen, damit der MemoryStream
Müll gesammelt werden kann. Close
und Dispose
befreien Sie weder den Dampfpuffer noch das MemoryStream
eigentliche Objekt.
Da weder ein Finalizer Stream
noch MemoryStream
ein Finalizer vorhanden sind, müssen Sie nicht aufrufen Close
oder aufrufen lassen Dispose
, GC.SuppressFinalize
um die Speicherbereinigung zu optimieren. Es gibt keinen zu unterdrückenden Finalizer.
In den Dokumenten für MemoryStream heißt es:
Dieser Typ implementiert die
IDisposable
Schnittstelle, verfügt jedoch nicht über Ressourcen, die entsorgt werden müssen. Dies bedeutet, dass das Entsorgen durch direktes AufrufenDispose()
oder Verwenden eines Sprachkonstrukts wieusing
(in C #) oderUsing
(in Visual Basic) nicht erforderlich ist.
Verwenden Sie using
block, damit Ihr Objekt entsorgt wird, wenn es die IDisposable
Schnittstelle implementiert
Welches rufe ich an?
Jeder von ihnen.
Ist es notwendig, beide anzurufen?
Nein, beides ist ausreichend.
Wird der andere eine Ausnahme auslösen, wenn ich bereits einen von ihnen angerufen habe?
Nein, das Einwegmuster erklärt, dass nachfolgende Aufrufe von Dispose keine negativen Auswirkungen haben.
In .NET 3.5 (andere Versionen wurden nicht überprüft) werden Methoden beim Entsorgen eines MemoryStream in der folgenden Reihenfolge aufgerufen:
Als erste Lösung wird empfohlen, wo immer möglich 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 Weise auf und bewirkt (wenn Sie sie wie oben gezeigt verwenden), dass das Objekt selbst den Gültigkeitsbereich verlässt, sobald Dispose aufgerufen wird. Innerhalb des using-Blocks ist das Objekt schreibgeschützt und kann nicht geändert oder neu zugewiesen werden.
Wenn wir jetzt zu der Frage kommen, wie andere in den meisten .NET Framework-Klassen vorgeschlagen haben, gibt es keinen Unterschied zwischen Close () und Dispose (), und es spielt keine Rolle, welche der beiden Methoden Sie aufrufen. Sie sollten einen anrufen, aber nicht beide. Es gibt jedoch Ausnahmen .
Es gibt Ausnahmen; Beispielsweise haben System.Windows.Forms.Form und System.Data.SqlClient.SqlConnection ein unterschiedliches Verhalten für Close () und Dispose ().
Ausführliche Informationen finden Sie hier: https://blogs.msdn.microsoft.com/kimhamil/2008/03/15/the-often-non-difference-between-close-and-dispose/