2008-11-25 12 views
23

Ich würde gerne wissen, wann ich Dinge in einen USING Block verpacken sollte und sollte.C# USING Schlüsselwort - wann und wann nicht?

Von dem, was ich verstehe, übersetzt der Compiler es in ein try/schließlich, wo die schließlich Dispose() auf das Objekt aufruft.

Ich benutze immer ein USING um Datenbankverbindungen und Dateizugriff, aber es ist eher aus Gewohnheit als ein 100% Verständnis. Ich weiß, dass Sie (oder mit einer Verwendung) Dispose() Objekte, die Ressourcen kontrollieren, sollten, um sicherzustellen, dass sie sofort freigegeben werden, anstatt wann immer die CLR sich anfühlt, aber das ist, wo mein Verständnis zusammenbricht.

Werden IDisposables nicht gelöscht, wenn sie den Gültigkeitsbereich verlassen?

Muss ich nur ein USING verwenden, wenn mein Objekt Dispose verwendet, um sich aufzuräumen?

Dank

Edit: Ich weiß, dass es ein paar andere Beiträge über das Schlüsselwort USING sind, aber ich bin mehr in den Antworten interessiert die die CLR im Zusammenhang und genau was intern

Andrew

los

Antwort

21

Nein, IDisposable Artikel werden nicht entsorgt, wenn sie außerhalb des Anwendungsbereichs liegen. Genau aus diesem Grund brauchen wir IDisposable - für deterministische Säuberung.

Sie werden schließlich bekommen Müll gesammelt, und wenn es einen Finalizer wird es (vielleicht) genannt werden - aber das könnte eine lange Zeit in der Zukunft sein (nicht gut für Verbindungspools usw.). Die Speicherbereinigung hängt vom Speicherdruck ab - wenn kein zusätzlicher Speicher benötigt wird, muss kein GC-Zyklus ausgeführt werden.

Interessanterweise (vielleicht) gibt es einige Fälle, in denen "verwenden" ein Schmerz ist - wenn die angreifende Klasse manchmal eine Ausnahme auf Dispose() wirft. WCF ist ein Täter davon. Ich habe dieses Thema (mit einer einfachen Problemumgehung) besprochen here.

Grundsätzlich - wenn die Klasse implementiert IDisposable, und Sie eigene eine Instanz (d. H. Sie erstellt oder was auch immer), ist es Ihre Aufgabe, sicherzustellen, dass es entsorgt wird. Das könnte bedeuten "über" zu verwenden, oder es könnte bedeuten, es an einen anderen Code zu übergeben, der Verantwortung übernimmt.

Ich habe tatsächlich Debug-Code des Typs gesehen: "Sind IDisposables nicht entsorgt, wenn sie gehen out of scope"

#if DEBUG 
    ~Foo() { 
     // complain loudly that smoebody forgot to dispose... 
    } 
#endif 

(wo die Dispose Anrufe GC.SuppressFinalize)

+0

Und wenn Sie diese Technik verwenden, bitte, bitte, vergessen Sie nicht die '#if DEBUG'. Das sind Sie, ich denke an JetBrains, mit Ihren 30000 Objekten in der Finalizer-Warteschlange von Visual Studio ... –

+2

Oh, das ist bedauerlich. –

+0

+1, ich wünschte, ich könnte mehr tun als 1 Stimme nach oben: p ... exzellentes Wissen wird auf Stackoverlow geteilt .... es ist einfach toll ... –

5

Nr Wenn das IDisposable Objekt finalizable ist, was nicht dasselbe ist, dann wird es fertig gestellt werden, wenn es Müll gesammelt ist.

Welches könnte bald sein oder könnte fast nie sein.

Jeff Richters C#/CLR Buch ist sehr gut in all diesen Sachen, und das Framework Design Guidelines Buch ist auch nützlich.

Benötige ich nur weiter verwenden zu verwenden, wenn mein Objekt Verwendung von Dispose macht selbst zu aufräumen?

Sie können nur Verwendung 'mit', wenn das Objekt IDisposable implementiert. Der Compiler wird ablehnen, wenn Sie versuchen, etwas anderes zu tun.

2

Um zu den anderen Antworten hinzuzufügen, sollten Sie using (oder ein explizites Dispose) verwenden, wenn ein Objekt andere Ressourcen als verwalteten Speicher enthält. Beispiele wären Dateien, Sockets, Datenbankverbindungen oder sogar GDI-Zeichnungsgriffe.

Der Garbage Collector würde schließlich diese Objekte finalisieren, aber nur zu einem unbestimmten Zeitpunkt in der Zukunft. Sie können sich nicht darauf verlassen, dass es rechtzeitig geschieht, und Sie könnten in der Zwischenzeit aus dieser Ressource ausgegangen sein.

+2

Man sollte einfach "verwenden", wenn die Klasse implementiert IDisposable. Was es tut, ist ein Implementierungsdetail ;-p Es ist ein * Finalizer *, den Sie nur hinzufügen sollten, wenn Ihre Klasse eine nicht verwaltete Ressource einpackt. Es gibt Beispiele für IDisposable in rein verwaltetem Code ... –

+0

Netter Kommentar, sollte es eine Antwort für einige Stimmen gemacht haben Liebe xx –

+0

Marc: du hast recht. Ich glaube, ich versuchte wirklich, die Motivation dafür zu erklären, warum der Implementierer eine Klasse IDisposable gemacht haben könnte, anstatt eine Müllsammlung, die alle Ressourcenmanagementprobleme löst. – babbageclunk

Verwandte Themen