Wann würde ich IDispose in einer Klasse im Gegensatz zu einem Destruktor implementieren? Ich habe diesen Artikel gelesen , aber ich vermisse immer noch den Punkt.
Ich gehe davon aus, dass ich IDispose, wenn ich es für ein Objekt implementiere, explizit "zerstören" kann, anstatt darauf zu warten, dass der Garbage Collector dies tut. Ist das richtig?
Bedeutet das, dass ich Dispose für ein Objekt immer explizit aufrufen sollte? Was sind einige gängige Beispiele dafür?
c#
.net
dispose
destructor
Jordan Parmer
quelle
quelle
using
Konstrukt tun .Antworten:
Ein Finalizer (auch Destruktor genannt) ist Teil der Garbage Collection (GC) - es ist unbestimmt, wann (oder sogar wenn) dies geschieht, da GC hauptsächlich aufgrund des Speicherdrucks erfolgt (dh mehr Speicherplatz benötigt). Finalizer werden normalerweise nur zum Bereinigen nicht verwalteter Ressourcen verwendet, da verwaltete Ressourcen über eine eigene Sammlung / Entsorgung verfügen.
Daher
IDisposable
wird verwendet, um Objekte deterministisch zu bereinigen, dh jetzt. Es sammelt nicht den Speicher des Objekts (der noch zu GC gehört), sondern wird beispielsweise zum Schließen von Dateien, Datenbankverbindungen usw. verwendet.Es gibt viele frühere Themen zu diesem Thema:
Beachten Sie schließlich, dass es nicht ungewöhnlich ist, dass ein
IDisposable
Objekt auch einen Finalizer hat. In diesem Fall werdenDispose()
normalerweise Aufrufe ausgeführtGC.SuppressFinalize(this)
, was bedeutet, dass GC den Finalizer nicht ausführt - es wirft einfach den Speicher weg (viel billiger). Der Finalizer wird weiterhin ausgeführt, wenn SieDispose()
das Objekt vergessen haben .quelle
Die
Finalize()
Methode besteht darin, sicherzustellen, dass ein .NET-Objekt nicht verwaltete Ressourcen bereinigen kann, wenn Müll gesammelt wird . Objekte wie Datenbankverbindungen oder Dateihandler sollten jedoch so bald wie möglich freigegeben werden, anstatt sich auf die Speicherbereinigung zu verlassen. Dazu sollten Sie dieIDisposable
Schnittstelle implementieren und Ihre Ressourcen in derDispose()
Methode freigeben .quelle
Es gibt eine sehr gute Beschreibung auf MSDN :
quelle
Das einzige, was in einem C # -Destruktor enthalten sein sollte, ist diese Zeile:
Das ist es. Nichts anderes sollte jemals in dieser Methode sein.
quelle
Ihre Frage, ob Sie immer anrufen sollten oder nicht,
Dispose
ist normalerweise eine hitzige Debatte. In diesem Blog finden Sie eine interessante Perspektive von angesehenen Personen in der .NET-Community.Persönlich denke ich, dass Jeffrey Richters Position, dass Anrufe
Dispose
nicht obligatorisch sind, unglaublich schwach ist. Er gibt zwei Beispiele, um seine Meinung zu rechtfertigen.Im ersten Beispiel sagt er, dass das Aufrufen
Dispose
von Windows Forms-Steuerelementen in Mainstream-Szenarien mühsam und unnötig ist. Er erwähnt jedoch nicht, dassDispose
Steuercontainer in diesen Mainstream-Szenarien tatsächlich automatisch aufgerufen werden.Im zweiten Beispiel gibt er an, dass ein Entwickler fälschlicherweise annehmen könnte, dass die Instanz von
IAsyncResult.WaitHandle
aggressiv entsorgt werden sollte, ohne zu bemerken, dass die Eigenschaft das Wartehandle träge initialisiert, was zu einer unnötigen Leistungseinbuße führt. Das Problem bei diesem Beispiel ist jedoch, dass dasIAsyncResult
selbst nicht den von Microsoft veröffentlichten Richtlinien für den Umgang mitIDisposable
Objekten entspricht. Wenn eine Klasse einen Verweis auf einenIDisposable
Typ enthält, sollte die Klasse selbst implementiert werdenIDisposable
. WennIAsyncResult
diese Regel befolgt wird, kann die eigeneDispose
Methode entscheiden, welches ihrer Mitglieder entsorgt werden muss.Wenn also nicht jemand ein überzeugenderes Argument hat, werde ich im Lager "Immer anrufen" entsorgen bleiben, mit dem Verständnis, dass es einige Randfälle geben wird, die hauptsächlich aus schlechten Designentscheidungen resultieren.
quelle
Es ist wirklich ziemlich einfach. Ich weiß, dass es beantwortet wurde, aber ich werde es erneut versuchen, aber ich werde versuchen, es so einfach wie möglich zu halten.
Ein Destruktor sollte im Allgemeinen niemals verwendet werden. Es wird nur ausgeführt .net möchte, dass es ausgeführt wird. Es wird nur nach einem Müllsammelzyklus ausgeführt. Es wird möglicherweise nie während des Lebenszyklus Ihrer Anwendung ausgeführt. Aus diesem Grund sollten Sie niemals Code in einen Destruktor einfügen, der ausgeführt werden muss. Sie können sich auch nicht darauf verlassen, dass vorhandene Objekte in der Klasse vorhanden sind, wenn sie ausgeführt werden (sie wurden möglicherweise bereits bereinigt, da die Reihenfolge, in der Destruktoren ausgeführt werden, nicht garantiert ist).
IDisposible sollte immer dann verwendet werden, wenn Sie ein Objekt haben, das Ressourcen erstellt, die bereinigt werden müssen (z. B. Datei- und Grafikhandles). Tatsächlich argumentieren viele, dass alles, was Sie in einen Destruktor einfügen, aus den oben genannten Gründen nicht verfügbar sein sollte.
Die meisten Klassen rufen dispose auf, wenn der Finalizer ausgeführt wird, aber dies dient lediglich als Schutz und sollte niemals als verlässlich angesehen werden. Sie sollten explizit alles entsorgen, was IDisposable implementiert, wenn Sie damit fertig sind. Wenn Sie IDisposable implementieren, sollten Sie dispose im Finalizer aufrufen. Ein Beispiel finden Sie unter http://msdn.microsoft.com/en-us/library/system.idisposable.aspx .
quelle
Hier ist ein weiterer guter Artikel, der den Nebel um IDisposable, den GC und die Entsorgung beseitigt.
Chris Lyons WebLog entmystifizierende Entsorgung
quelle