Ich habe an einigen Stellen Code mit folgender Logik gesehen:
%Vor%Was ist der Grund dafür, foo im Wörterbuch auf null zu stellen, bevor Sie es entfernen?
Ich dachte, die Garbage-Collection interessiert sich für die Anzahl der Dinge, die auf den ursprünglichen * foo verweisen. Wenn das der Fall ist, würde die Einstellung von myDictonary ["foo"] auf null nicht einfach die Anzahl um eins verringern? Würde nicht dasselbe passieren, wenn myDictonary.Remove ("foo") aufgerufen wird?
Was ist der Punkt von _myDictonary ["foo"] = null;
edit: Zur Klärung - als ich sagte "entferne die Zählung um eins" meinte ich folgendes:
- myDictonary ["foo"] zeigt ursprünglich auf ein Objekt. Das bedeutet, das Objekt hat ein oder mehrere Dinge, die darauf verweisen.
- Sobald myDictonary ["foo"] auf null gesetzt ist, verweist es nicht mehr auf dieses Objekt. Dies bedeutet, dass Objekt eine weniger Sache hat, die darauf verweist.
Es gibt überhaupt keinen Sinn.
Wenn Sie sich ansehen, was die Methode Remove
tut (mit .NET Reflector), finden Sie Folgendes:
Diese Zeile setzt den Wert des Wörterbuchelements auf null, da der Standardwert für einen Referenztyp null ist. Wenn also die Remove
-Methode den Verweis auf Null setzt, hat es keinen Sinn, dies vor dem Aufruf der Methode zu tun.
Wenn Sie einen Wörterbucheintrag auf null
setzen, verringert nicht die ref-Zählung, da null
ein perfekt geeigneter Wert ist, auf den in einem Wörterbuch verwiesen wird.
Die beiden Aussagen machen sehr unterschiedliche Dinge. Wenn Sie den Wert auf null
setzen, bedeutet dies, dass der Wert für diesen Schlüssel sein sollte, während das Entfernen dieses Schlüssels aus dem Wörterbuch anzeigt, dass er nicht mehr vorhanden sein sollte.
Es gibt nicht viel Sinn.
Wenn jedoch die Remove
-Methode Heapzuweisungen verursacht und der gespeicherte Wert groß ist, kann beim Aufruf von Remove
eine Garbage Collection erfolgen, und der Wert kann auch im Prozess gesammelt werden (wodurch möglicherweise Speicher freigegeben wird) ). In der Praxis kümmern sich die Leute normalerweise nicht um kleine Dinge wie diese, es sei denn, sie wurden gezeigt , um nützlich zu sein.
Bearbeiten:
Vergessen zu erwähnen: Im Idealfall sollte sich das Wörterbuch selbst um seine eigene Implementierung kümmern, nicht den Anrufer.
Es macht dort nicht viel Sinn, aber es gibt Zeiten, in denen es Sinn macht.
Ein Beispiel ist in einer Dispose()
-Methode. Betrachte diesen Typ:
Sie könnten jetzt argumentieren, dass dies unnötig ist, und Sie haben meistens Recht. Normalerweise Dispose()
wird nur aufgerufen, bevor Owner
dereferenziert wird, und wenn Owner
gesammelt wird, wird _bigAllocation
ebenfalls ... schließlich.
Allerdings:
Wenn _bigAllocation
auf null gesetzt wird, ist es sofort für die Sammlung geeignet , wenn niemand sonst einen Verweis darauf hat. Dies kann vorteilhaft sein, wenn Owner
in einer GC-Generation mit höherer Nummer steht oder einen Finalizer hat. Andernfalls muss Owner
freigegeben werden, bevor _bigAllocation
für die Erfassung ausgewählt werden kann.
Dies ist jedoch eine Art Eckfall. Die meisten Typen sollten keine Finalizer haben und in den meisten Fällen wären _bigAllocation
und Owner
in derselben Generation.
Ich könnte mir vorstellen, dass dies in einer Multithread-Anwendung nützlich ist, in der Sie das Objekt auf null setzen, damit kein anderer Thread darauf operieren kann. Allerdings scheint dies schwer zu handhaben und schlechtes Design.
Wenn dies der Fall ist, würde myDictonary ["foo"] nicht auf null gesetzt einfach die Anzahl um eins verringern?
Nein, die Anzahl ändert sich nicht, der Verweis befindet sich immer noch im Wörterbuch, er zeigt auf Null.
Ich sehe keinen Grund dafür, dass der Code so ist.
Ich weiß nichts über die Interna von Dictionary im Speziellen, aber einige Arten von Sammlungen können Referenzen auf Objekte enthalten, die tatsächlich "tot" sind. Zum Beispiel kann eine Sammlung ein Array und eine Anzahl von wie vielen gültigen Elementen in dem Array enthalten; Wenn die Zählung auf null gesetzt würde, würden alle Elemente in der Sammlung nicht zugänglich sein, aber sie würden keine Referenzen auf sie zerstören. Es kann sein, dass das Löschen eines Elements aus einem Dictionary dazu führt, dass der Bereich, in dem das Objekt enthalten ist, wiederverwendet werden kann, ohne es tatsächlich zu löschen. Wenn ein anderes Element mit dem gleichen Hash-Code zum Wörterbuch hinzugefügt wird, wird das erste Element tatsächlich gelöscht, aber das passiert möglicherweise nie für eine Weile.
Das sieht nach einer alten C ++ Gewohnheit aus.
Ich vermute, dass der Autor sich Sorgen um ältere Sammlungen und / oder andere Sprachen macht. Wenn Speicher dient, würden einige Auflistungen in C ++ Zeiger auf die gesammelten Objekte enthalten, und wenn "entfernt" nur den Zeiger entfernen würde, aber nicht automatisch den Destruktor des neu entfernten Objekts aufrufen würde. Dies verursacht einen sehr subtilen Speicherverlust. Die Gewohnheit wurde, das Objekt auf null zu setzen, bevor es entfernt wurde, um sicherzustellen, dass der Destruktor aufgerufen wurde.
Tags und Links .net c# garbage-collection