2009-02-13 17 views
6

In dem folgenden C# -Code, wie werde ich die Objekte loswerden, wenn es nicht mehr sinnvoll ist? Wird es automatisch erledigt oder muss ich etwas tun?Wie entfernen Sie ein Objekt in C#

public void Test() 
{ 
    object MyObject = new object(); 

    ... code ... 
} 
+0

Sorry für den Schnitt, ich versuche nur, Probleme zu stoppen, bevor es versehentlich beginnt - nichts für ungut. –

+0

Lol, und ich * so * wollte, dass mir jemand sagte, wie man das * bestimmte * Variable löscht ... –

+0

@lc Und natürlich keine Beleidigung genommen :-) –

Antwort

5

Die kurze Antwort ist: es sei denn, es hat unmanaged Ressourcen (Datei behandelt etc) müssen Sie sich keine Sorgen machen.

Die lange Antwort ist ein bisschen mehr beteiligt.

Wenn .NET beschließt, etwas Speicher freizugeben, wird der Garbage Collector ausgeführt. Es sucht nach allen Objekten, die noch verwendet werden, und markiert sie als solche. Jede lokale Variable (in irgendeinem Stapelrahmen eines beliebigen Threads), die noch gelesen werden kann, zählt als root ebenso wie statische Variablen.(Tatsächlich glaube ich, dass statische Variablen über Live-Type-Objekte referenziert werden, die über Live-AppDomain-Objekte referenziert werden, aber größtenteils können Sie statische Variablen als Roots betrachten.)

Der Garbage Collector betrachtet jedes Objekt, auf das verwiesen wird durch eine Wurzel und findet dann mehr "lebende" Referenzen basierend auf den Instanzvariablen innerhalb dieser Objekte. Es regt sich auf und findet und markiert mehr und mehr Objekte als "live". Sobald es diesen Prozess beendet hat, kann es dann alle Rest der Objekte betrachten und sie befreien.

Das ist ein sehr breites konzeptionelles Bild ist - aber es viel detailliertere erhält, wenn Sie von der Generationen Modell der Garbage Collection denken, Finalizers, gleichzeitige Sammlung usw. stark Ich empfehle Ihnen, Jeff Richter CLR via C# lesen, die in diese geht in vielen Details. Er hat auch einen twopart Artikel (zurück aus dem Jahr 2000, aber immer noch sehr relevant), wenn Sie das Buch nicht kaufen wollen.

Natürlich bedeutet dies nicht, dass Sie sich keine Gedanken über Speicherauslastung und Objektlebensdauer in .NET machen müssen. Insbesondere gilt Folgendes:

  • Erstellen von Objekten pointlessly werden Kostenleistung. Insbesondere ist der Müllsammler schnell aber nicht frei. Suchen Sie nach einfache Möglichkeiten, um Ihren Speicherverbrauch zu reduzieren, wie Sie programmieren, aber Mikro-Optimierung, bevor Sie wissen, dass Sie ein Problem haben, ist auch schlecht.
  • Es ist möglich, Speicher zu "lecken", indem Objekte länger als beabsichtigt erreichbar gemacht werden. Zwei recht häufige Ursachen dafür sind statische Variablen und Ereignisabonnements. (Ein Ereignisabonnement macht den Ereignishandler vom Ereignisherausgeber aus erreichbar, aber nicht andersherum.)
  • Wenn Sie mehr Speicher (live, erreichbar) als verfügbar verwenden, stürzt Ihre App ab. Es gibt nicht viel .NET kann das verhindern!
  • Objekte, die Ressourcen ohne Arbeitsspeicher verwenden, implementieren normalerweise IDisposable. Sie sollten Dispose auf ihnen aufrufen, um diese Ressourcen freizugeben, wenn Sie mit dem Objekt fertig sind. Beachten Sie, dass nicht das Objekt selbst freigibt - nur der Garbage Collector kann das tun. Die using-Anweisung in C# ist die bequemste Methode, Dispose zuverlässig aufzurufen, selbst wenn es sich um eine Ausnahme handelt.
18

Automatisch. Wenn MyObject den Gültigkeitsbereich (am Ende von Test) verlässt, wird es für die Garbage Collection markiert. Irgendwann in der Zukunft, die .NET-Laufzeit wird den Speicher für Sie bereinigen

Edit: (Ich sollte der Vollständigkeit halber darauf hinweisen, dass, wenn Sie MyObject irgendwo übergeben, wird es durch Verweis übergeben, und wird nicht Müll gesammelt werden - es ist nur, wenn keine Referenzen mehr auf das Objekt herum schweben, dass der GC es kostenlos sammeln kann)

Edit: in einem Release-Build, MyObject wird in der Regel gesammelt, sobald es nicht verwendet wird (siehe meine Antwort für weitere Details - dp)

+0

Diese Antwort lässt den gesamten Prozess aktiver klingen als er ist. Nichts "markiert" das Objekt, wenn es den Bereich verlässt - es zählt nur nicht, wenn der GC versucht, Objekte zu finden, die * nicht * wegwerfen sollen. –

+0

Oh, und MyObject wird nur als Referenz mit "ref" übergeben. Ansonsten wird es nach Wert übergeben, aber der Wert * ist * eine Referenz. Sie sind nicht das Gleiche. –

+0

In Bezug auf die Bearbeitung von "dp" - "für GC anfänglich" zu werden ist nicht das Gleiche wie "wird normalerweise gesammelt, sobald es nicht verwendet wird" - Sie müssen immer noch auf den GC warten, um eine Sammlung durchzuführen. –

3

In optimiertem Code ist es möglich und wahrscheinlich, dass MyObject vor dem Ende der Methode gesammelt wird. Standardmäßig wird die Debug-Konfiguration in Visual Studio mit aktiviertem Debug-Schalter und aktivierter Ausschaltung erstellt, was bedeutet, dass MyObject bis zum Ende der Methode beibehalten wird (damit Sie den Wert während des Debuggings betrachten können). Das Erstellen mit optimize off (Debugging spielt in diesem Fall keine Rolle) ermöglicht, dass MyObject erfasst wird, nachdem festgestellt wurde, dass es nicht verwendet wird. Eine Möglichkeit, um sie am Ende der Methode am Leben zu erhalten, besteht darin, GC.KeepAlive (MyObject) am Ende der Methode aufzurufen.

4

Die anderen Antworten sind richtig, es sei denn, Ihr Objekt eine Instanz einer Klasse ist, die die IDisposable-Schnittstelle implementiert, wobei in diesem Fall, Sie sollten (explizit oder implizit über eine using-Anweisung) die Dispose Methode des Objekts aufrufen.

1

Normalerweise kann die Garbage Collection von der Säuberung abhängig sein, aber wenn Ihr Objekt nicht verwaltete Ressourcen (Datenbankverbindungen, offene Dateien usw.) enthält, müssen Sie diese Ressourcen explizit schließen und/oder die dispose-Methode für das Objekt ausführen es implementiert IDisposable). Dies kann zu Fehlern führen, daher müssen Sie vorsichtig sein, wie Sie mit diesen Arten von Objekten umgehen. Das einfache Schließen einer Datei nach der Verwendung ist nicht immer ausreichend, da eine Ausnahme vor dem Schließen die Datei geöffnet lässt. Verwenden Sie entweder einen using-Block oder einen try-finally-Block.

Fazit: "using" ist dein Freund.

2

Dadurch wird der Garbage Collector gezwungen, unbenutzte Objekte loszuwerden.

GC.Collect(); 
GC.WaitForPendingFinalizers(); 

Wenn Sie ein bestimmtes Objekt gesammelt werden möchten.

+1

Es muss nicht auf null gesetzt werden, wenn es sich um eine lokale Variable handelt, die im Rest der Methode nicht verwendet wird. (Angenommen, Sie laufen im Freigabemodus.) –

Verwandte Themen