Frage Wie werden Sie ein Objekt in c # loswerden


Wie entferne ich im folgenden c # -Code die Objekte, wenn sie nicht mehr nützlich sind? Wird es automatisch erledigt oder muss ich etwas tun?

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

   ... code ...
}

6
2018-02-13 01:55


Ursprung


Antworten:


Die kurze Antwort lautet: Wenn Sie keine nicht verwalteten Ressourcen (Dateihandles usw.) haben, müssen Sie sich keine Sorgen machen.

Die lange Antwort ist ein bisschen mehr beteiligt.

Wenn .NET beschließt, etwas Speicher freizugeben, führt es das Müllsammler. 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 a Wurzel 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 sich ein Root bezieht, und findet dann weitere "Live" -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 betrachten sich ausruhen der Objekte und befreie sie.

Das ist ein sehr weit gefächertes konzeptuelles Bild - aber es wird viel detaillierter, wenn man an das denkt Generation Modell der Müllsammlung, Finalizer, gleichzeitige Sammlung usw. Ich empfehle dringend, dass Sie Jeff Richter lesen CLR über C # das geht sehr detailliert in das ein. Er hat auch eine zwei  Teil Artikel (zurück aus dem Jahr 2000, aber immer noch sehr relevant), wenn Sie das Buch nicht kaufen wollen.

All dies bedeutet natürlich nicht, dass Sie sich nicht um die Speichernutzung und die Lebensdauer von Objekten in .NET kümmern müssen. Bestimmtes:

  • Objekte sinnlos erstellen werden Preis-Leistungsverhältnis. Insbesondere ist der Müllsammler schnell aber nicht frei. Suche einfach Möglichkeiten, die Speichernutzung beim Codieren zu reduzieren, aber die Mikrooptimierung, bevor Sie wissen, dass Sie ein Problem haben, ist ebenfalls 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 Ereignisverleger erreichbar, aber nicht umgekehrt.)
  • Wenn du mehr Speicher verwendest (in einer live, erreichbaren Weise), als du zur Verfügung hast, stürzt deine App ab. Es gibt nicht viel .NET kann das verhindern!
  • Objekte, die Ressourcen ohne Arbeitsspeicher verwenden, werden normalerweise implementiert IDisposable. Du solltest anrufen Dispose auf ihnen, diese Ressourcen freizugeben, wenn Sie mit dem Objekt fertig sind. Beachten Sie, dass dies nicht befreie das Objekt selbst - nur der Garbage Collector kann das tun. Das using Anweisung in C # ist die bequemste Art des Aufrufs Dispose zuverlässig, auch angesichts einer Ausnahme.

5
2018-02-13 07:34



Automatisch. Wenn MyObject den Gültigkeitsbereich (am Ende von Test) verlässt, wird es für die Garbage Collection markiert. Zu einem späteren Zeitpunkt wird die .NET-Laufzeit den Speicher für Sie bereinigen

Bearbeiten: (Ich möchte der Vollständigkeit halber darauf hinweisen, dass wenn Sie MyObject irgendwohin übergeben, wird es als Referenz weitergegeben und nicht als Müll gesammelt. Nur wenn keine Referenzen mehr auf das Objekt übertragen werden, kann der GC diese sammeln )

Bearbeiten: In einem Release-Build wird MyObject normalerweise gesammelt, sobald es nicht mehr verwendet wird (siehe meine Antwort für weitere Details - dp)


18
2018-02-13 01:57



Die anderen Antworten sind korrekt, es sei denn, Ihr Objekt ist eine Instanz einer Klasse, die das Objekt implementiert IDisposable Schnittstelle, in welchem ​​Fall Sie (explizit oder implizit über a using Anweisung) rufen Sie das Objekt auf Dispose Methode.


4
2018-02-13 02:10



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.


3
2018-02-13 02:10



Dadurch wird der Garbage Collector gezwungen, nicht verwendete Objekte zu entfernen.

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

Wenn Sie möchten, dass ein bestimmtes Objekt erfasst wird.

object A = new Object();
...
A = null;
GC.collect();
GC.WaitForPendingFinalizers();

2
2018-02-13 04:19



Es wird automatisch erledigt.


1
2018-02-13 01:57



In der Regel kann die Garbage Collection von der Bereinigung 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 (wenn IDisposable implementiert wird). . 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.


1
2018-02-13 03:29