Angenommen, es gibt den folgenden Code:
%Vor%Von Zeit zu Zeit bin ich versucht, Referenzen auf Null zu setzen, genau so wie die Prozedur beendet wird (also zurückkehrt) oder in diesem Fall, genau wie es im Begriff ist, eine Schleife zu machen. Gibt es einen Vorteil, auch wenn ein kleiner?
Dies hat keinen Vorteil für lokale Variablen. Die CLR weiß mittels des JIT genau, wann eine lokale Variable innerhalb einer Methode nicht mehr verwendet wird und damit sammelbar ist.
Raymond Chen hat kürzlich einen sehr ausführlichen Blog-Artikel darüber geschrieben, wann genau Objekte gesammelt werden können. Es umfasst dieses Szenario im Detail und ist das Lesen wert
Es gibt jedoch einige Ausnahmen von dieser Regel. Wenn die fragliche lokale Variable in einem Abschluss oder einem Iterator erfasst wird, hat das Ja-Nullen der Variablen eine Auswirkung. Nämlich weil das Local nicht länger ein Local ist, sondern ein Feld und hat eine andere GC-Semantik.
Nein. In der Tat kann das "Nullen" lokaler Variablen unter bestimmten Umständen die Speicherbereinigung verhindern. Sobald eine Variable im normalen Betrieb nicht mehr von einem Ausführungscode aus erreichbar ist, wird sie für die Garbage Collection verfügbar. Wenn Sie am Ende Ihrer Methode die Variable "ausschließen", behalten Sie sie bis zu diesem Moment "am Leben" und verzögern tatsächlich ihre Verfügbarkeit für die Garbage Collection.
Ich schrieb einen langen und erschöpfenden Blogartikel, der antwortet diese Frage .
Zusammenfassend lautet die allgemeine Antwort "nein; es gibt keinen Nutzen". Es gibt jedoch einige Sonderfälle:
IDisposable.Dispose
auf null zu setzen, diesen Test nicht erfüllt und nicht empfohlen werden sollte.] Fazit: Im Allgemeinen wird das Festlegen von Variablen auf null, um den Garbage Collector zu unterstützen, nicht empfohlen. Wenn es als notwendig erachtet wird, liegt ein ungewöhnlicher Zustand vor und sollte im Code sorgfältig dokumentiert werden.
Wenn eine Klasse über einen Finalizer verfügt, führen alle Nicht-Null-Objektreferenzfelder dazu, dass die Objekte, auf die verwiesen wird, länger gehalten werden als sie es sonst tun würden. Wenn bekannt ist, dass die Objekte bereits vor Ausführung des Finalizers nicht mehr benötigt werden, können durch das Entfernen der Objektreferenzfelder die Objekte früher "generiert" werden, als dies sonst der Fall wäre. Das kann ein großer Gewinn sein.
Wenn erwartet wird, dass die Lebensdauer (nützlich oder nicht) eines Objekts die nutzbare Lebensdauer eines Objekts übertrifft, auf das es eine Referenz hat, verhindert das unnötige Halten einer Referenz, dass das letzte Objekt erfasst wird, bis das erstere ist Referenz wird zwingen, das letztere Objekt zu behalten, selbst nachdem es nutzlos geworden ist). Durch das Löschen der Referenz wird dieses Problem vermieden.
Wenn eine in vb.net geschriebene Klasse irgendwelche "WithEvents-Variablen" hat, sollten sie jedes Mal gelöscht werden (setzen Sie sie auf nichts), wenn das Objekt, das sie enthält, nutzlos wird. Eine Klasse kann nicht als Garbage-Collection betrachtet werden, wenn sie einen Verweis auf ein Live-Objekt in einer "WithEvents-Variablen" enthält. Wenn z.B. Ein Enumerator enthält eine "WithEvents" -Referenz auf eine zugrunde liegende Sammlung (z. B. kann er Ereignisse empfangen, wenn / wenn die Sammlung geändert wird) und sein Dispose-Handler seinen Verweis auf die zugrunde liegende Sammlung nicht löscht. Der Enumerator wird solange am Leben gehalten die zugrunde liegende Sammlung ist. Wenn die Auflistung sehr oft aufgezählt wird, könnte dies zu einem massiven Speicherverlust führen.
Nein. Lass den GC seine Arbeit machen und hilf ihm nur wenn es nötig ist.
Es gibt einen wichtigen Fall, in dem das Nullen eine Auswirkung hat, wenn Sie einen Debug-Build mit einigen deaktivierten JIT-Optimierungen verwenden. Ein Großteil des Funker-Verhaltens, wenn Objekte aufgeräumt werden, kann aufhören, das Debuggen zu erleichtern.
Es ist wichtig, weil es zu einer falschen Sicht auf das, was im Release-Build passiert, führen kann.
Und die Antwort ist: Ja, wenn Sie wissen, was Sie tun! Aber es ist vorzeitige Optimierung (die Wurzel aller Übel für viele Personen), also sollten Sie es nicht tun, es sei denn, Sie brauchen wirklich den Speicher.
Nun werde ich nur zwei Fälle analysieren, in denen es nützlich sein könnte.
Eigenschaften eines Objekts, von dem Sie wissen, dass es nicht mehr referenziert wird (zum Beispiel haben Sie eine komplexe Berechnung in einer privaten Eigenschaft zwischengespeichert. Sie wissen, dass Sie nicht mehr brauchen werden, Sie säubern es) Aber dieses wurde gesagt von vielen Personen
Felder in komplexen Methoden. Dies ist das Gegenteil von dem, was andere gesagt haben, aber ich habe ein Beispiel, also weiß ich, dass ich recht habe :-) Nun, normalerweise, in einer sequentiellen Methode kann der GC sehen, wo ein lokaler ist Die Referenz wird nicht mehr verwendet (technisch gesehen ist der wichtigste Teil, wenn sie nicht mehr gelesen wird. Und das Aufrufen von Methoden der Variablen ist "Lesen". Das Schreiben in eine Variable zählt nicht, denn wenn niemand den neuen Wert liest, ist es nutzlos schreibe es)
Aber ich habe sequentielle Methode gesagt. Und nicht sequentielle Methoden? Lass es uns versuchen! (Klar habe ich es schon gemacht! Ich werde kein ideone Beispiel machen, weil der GC von mono anders ist als der GC von .NET).
Kompilieren Sie diesen Code im Modus Release und führen Sie ohne den Debugger (also STRG-F5) aus, und beobachten Sie die Ergebnisse:
%Vor%Die Ergebnisse:
%Vor% Eine Erklärung: Dieses Programm ist ein Beispiel für ein zyklisches Programm, bei dem ein großes Objekt außerhalb des Zyklus initialisiert wird (a for
cycle) und das große Objekt nur in einem Teil des Zyklus verwendet wird (zum Beispiel in den ersten 100) Iterationen). Offensichtlich kann der GC nicht leicht erkennen, dass ab dem Ende der Iteration 99 (der 100. Iteration, 0-99) auf das Objekt nicht mehr Bezug genommen wird.
Aber erinnere dich an die Worte vorzeitige Optimierung und Wurzel aller Übel ! : -)
Tags und Links .net garbage-collection