it-swarm.com.de

Was ist der Unterschied zwischen der Verwendung von IDisposable und einem Destruktor in C #?

Wann würde ich IDispose in einer Klasse anstatt in einem Destruktor implementieren? Ich lese diesen Artikel , aber ich verpasse immer noch den Punkt.

Ich gehe davon aus, dass ich, wenn ich IDispose für ein Objekt implementiere, es explizit "zerstören" kann, anstatt darauf zu warten, dass der Garbage Collector es tut. Ist das richtig?

Heißt das, ich sollte Dispose für ein Objekt immer explizit aufrufen? Was sind einige gängige Beispiele dafür?

95
Jordan Parmer

Ein Finalizer (auch bekannt als Destruktor) ist Teil der Garbage Collection (GC) - es ist unbestimmt, wann (oder sogar wenn) dies geschieht, da GC hauptsächlich aufgrund von Speicherdruck auftritt (d. H. Mehr Speicherplatz benötigen). Finalizer werden normalerweise nur zum Bereinigen von nicht verwalteten Ressourcen verwendet, da verwaltete Ressourcen über eine eigene Sammlung/Entsorgung verfügen.

Daher wird IDisposable verwendet, um deterministisch Objekte zu bereinigen, d. H. Jetzt. Es sammelt nicht den Speicher des Objekts (der immer noch zu GC gehört) - sondern wird zum Beispiel 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 ruft Dispose() normalerweise GC.SuppressFinalize(this) auf, was bedeutet, dass GC den Finalizer nicht ausführt - er wirft einfach den Speicher weg (viel billiger). Der Finalizer wird weiterhin ausgeführt, wenn Sie das Objekt vergessen haben, Dispose().

118
Marc Gravell

Die Funktion der Finalize() -Methode besteht darin, sicherzustellen, dass ein .NET-Objekt nicht verwaltete Ressourcen bereinigen kann wenn Garbage Collected. Objekte wie Datenbankverbindungen oder Datei-Handler sollten jedoch so schnell wie möglich freigegeben werden, anstatt sich auf die Garbage Collection zu verlassen. Dazu sollten Sie die Schnittstelle IDisposable implementieren und Ihre Ressourcen in der Methode Dispose() freigeben.

23
Igal Tabachnik

Es gibt eine sehr gute Beschreibung zu MSDN :

Die primäre Verwendung dieser Schnittstelle besteht darin, nicht verwaltete Ressourcen freizugeben . Der Garbage Collector gibt den einem verwalteten Objekt zugewiesenen Speicher automatisch frei, wenn dieses Objekt nicht mehr verwendet wird. Es ist jedoch nicht möglich vorherzusagen, wann eine Speicherbereinigung stattfinden wird . Darüber hinaus hat der Garbage Collector keine Kenntnis über nicht verwaltete Ressourcen wie Fenster-Handles oder geöffnete Dateien und Streams.

Verwenden Sie die Dispose-Methode dieser Schnittstelle, um nicht verwaltete Ressourcen in Verbindung mit dem Garbage Collector explizit freizugeben . Der Consumer eines Objekts kann diese Methode aufrufen, wenn das Objekt nicht mehr benötigt wird.

9
abatishchev

Das einzige, was in einem C # -Destruktor sein sollte, ist diese Zeile:

Dispose(False);

Das ist es. Nichts anderes sollte jemals in dieser Methode sein.

8
Jonathan Allen

Ihre Frage, ob Sie immer Dispose anrufen sollen oder nicht, ist normalerweise eine hitzige Debatte. In this blog finden Sie eine interessante Perspektive von angesehenen Personen in der .NET-Community.

Persönlich denke ich, dass Jeffrey Richters Position, dass das Aufrufen von Dispose nicht obligatorisch ist, unglaublich schwach ist. Er nennt zwei Beispiele, um seine Meinung zu rechtfertigen.

Im ersten Beispiel sagt er, dass das Aufrufen von Dispose in Windows Forms-Steuerelementen in Mainstream-Szenarios mühsam und unnötig ist. Er erwähnt jedoch nicht, dass Dispose in diesen Mainstream-Szenarien von Steuercontainern automatisch aufgerufen wird.

Im zweiten Beispiel gibt er an, dass ein Entwickler fälschlicherweise annehmen könnte, dass die Instanz von IAsyncResult.WaitHandle sollte aggressiv entsorgt werden, ohne zu bemerken, dass die Eigenschaft das Wait-Handle träge initialisiert, was zu unnötigen Leistungseinbußen führt. Das Problem bei diesem Beispiel ist jedoch, dass IAsyncResult selbst nicht den von Microsoft veröffentlichten Richtlinien für den Umgang mit IDisposable Objekten entspricht. Das heißt, wenn eine Klasse einen Verweis auf einen IDisposable -Typ enthält, sollte die Klasse selbst IDisposable implementieren. Wenn IAsyncResult dieser Regel folgt, könnte seine eigene Dispose Methode die Entscheidung darüber treffen, welches seiner konstituierenden Mitglieder entsorgt werden muss.

Wenn also nicht jemand ein zwingenderes Argument hat, werde ich im Lager "Immer entsorgen" bleiben, mit dem Verständnis, dass es einige Randfälle geben wird, die größtenteils auf schlechte Designentscheidungen zurückzuführen sind.

4
Brian Gideon

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 generell niemals verwendet werden. Es wird nur ausgeführt .net möchte, dass es ausgeführt wird. Es wird erst nach einem Garbage Collectoin-Zyklus 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 innerhalb der Klasse existieren, wenn sie ausgeführt werden (möglicherweise wurden sie 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 bereinigungsbedürftige Ressourcen erstellt (z. B. Datei- und Grafikhandles). Tatsächlich argumentieren viele, dass alles, was Sie in einen Destruktor stecken, aus den oben genannten Gründen in IDisposable gesetzt werden sollte.

Die meisten Klassen rufen dispose auf, wenn der Finalizer ausgeführt wird. Dies ist jedoch nur ein sicherer Schutz, auf den Sie sich niemals verlassen sollten. Sie sollten alles, was IDisposable implementiert, explizit entsorgen, wenn Sie damit fertig sind. Wenn Sie IDisposable implementieren, sollten Sie dispose in finalizer aufrufen. Ein Beispiel finden Sie unter http://msdn.Microsoft.com/en-us/library/system.idisposable.aspx .

2
DaEagle

Hier ist ein weiterer feiner Artikel, der einen Teil des Nebels um IDisposable, den GC, aufräumt und entsorgt.

Chris Lyons WebLog Demystifying Dispose

0
scope_creep