Alle schwachen internen Sammlungen (für unveränderliche Objekte)

In einigen Situationen mit unveränderlichen Objekten können viele verschiedene Objekte entstehen, die semantisch identisch sind. Ein einfaches Beispiel wäre das Lesen vieler Textzeilen aus einer Datei in Zeichenfolgen. Aus der Sicht des Programms wäre die Tatsache, dass zwei Zeilen dieselbe Zeichenfolge haben, "Zufall", aus der Sicht des Programmierers kann jedoch eine große Menge an Duplikaten erwartet werden. Wenn viele Zeichenfolgeninstanzen identisch sind, wird durch Ändern der Verweise auf diese unterschiedlichen Instanzen in Verweise auf eine einzelne Instanz Speicher gespart und es werden auch Vergleiche zwischen ihnen erleichtert (wenn zwei Zeichenfolgenverweise auf dieselbe Zeichenfolge verweisen, müssen keine Zeichen ausgeführt werden. Zeichenvergleich, um festzustellen, ob sie identisch sind).

In einigen Szenarien kann die vom System bereitgestellte Funktion zum Internieren von Zeichenfolgen hilfreich sein. Es gibt jedoch einige schwerwiegende Einschränkungen:

Sobald eine Zeichenfolge interniert ist, bleibt diese internierte Kopie für immer erhalten, unabhängig davon, ob eine andere Referenz darauf vorhanden ist oder nichtDie Funktion zum Internieren von Zeichenfolgen funktioniert nur mit Zeichenfolgen und kann nicht mit anderen unveränderlichen Typen verwendet werden.

Wenn es eine wahre gabWeakDictionary<ImmutableClassType, ImmutableClassType> (Für jedes Element wären der Schlüssel und der Wert identisch.) Code könnte folgendermaßen vorgehen:

if (theDict.TryGetValue(myString, ref internedString))
  myString = internedString;
else
  theDict[myString] = myString;

Leider sind mir keine eingebauten Funktionen bekanntWeakDictionary<keyType, valType> Klasse in .net. Darüber hinaus erscheint es verschwenderisch, eine schwache Referenz für den Schlüssel und den Wert jedes Elements zu generieren, wenn beide Referenzen immer auf dasselbe verweisen.

Ich habe etwas darüber gelesenConditionalWeakTable, und das klingt nach einer interessanten Klasse, aber ich denke nicht, dass es hier verwendbar wäre, da das Ziel darin besteht, eine Instanz zu nehmen und eine andere unabhängige Instanz zu finden, die semantisch äquivalent ist.

In Situationen, in denen Instanzen einer Klasse eine genau definierte Lebensdauer haben, kann es sinnvoll sein, eine konventionelle zu verwendenDictionary identische Instanzen zusammenführen. In vielen Fällen kann es jedoch schwierig sein zu wissen, wann eine solcheDictionary sollten aufgegeben oder die darin enthaltenen Gegenstände gereinigt werden. EINWeakReference-basierte interne Sammlung würde solche Probleme vermeiden. Gibt es so etwas oder könnte es ohne weiteres implementiert werden?

Nachtrag Wie Svick bemerkte, aDictionary<WeakReference, WeakReference> wäre etwas problematisch, da es keinen praktischen Weg gibt, eine zu definierenIEqualityComparer was würde ein Leben habenWeakReference Gib die ... wiederGetHashCode Wert seines Ziels, und haben einen Toten weiterhin diesen Wert zurückzugeben. Man könnte eine Struktur definieren, die einen ganzzahligen Ziel-Hashcode-Wert enthält (im Konstruktor festgelegt) und deren eigenenGetHashCode würde diese ganze Zahl zurückgeben. Eine leichte Verbesserung könnte darin bestehen, aConditionalWeakTable das Ziel der verknüpfenWeakReference auf ein finalisierbares Objekt, mit dem Tabellenelemente zum Löschen in die Warteschlange gestellt werden können.

Ich bin mir nicht sicher, wie das richtige Gleichgewicht zwischen dem Versuch, das Wörterbuch eifrig zu bereinigen, und dem Versuch, etwas passiver vorzugehen (z. B. beim Hinzufügen eines Elements einen Sweep durchzuführen, wenn seit dem letzten Sweep mindestens ein GC vorhanden ist, und der Anzahl) Anzahl der Elemente, die seit dem letzten Sweep hinzugefügt wurden, überschreitet die Anzahl der Elemente, die das Sweep überlebt haben. Es wird nicht kostenlos sein, alles im Wörterbuch zu durchsuchen, aber ConditionalWeakTable wird wahrscheinlich auch nicht kostenlos sein.

PPS Ein anderer Gedanke, an den ich dachte, aber ich dachte, er wäre wahrscheinlich nicht so nützlich wie ein schwacher interner Ansatz, würde darin bestehen, einen logisch unveränderlichen Typ zu haben, der einen veränderlichen "Zeitstempel" -Wert enthält, und eine Vergleichsmethode zu haben, die seinen akzeptiert Argumente vonref. Wenn zwei verschiedene Instanzen als gleich befunden werden, werden ihre Zeitstempelwerte untersucht. Wenn beide Null sind, werden ihnen fortlaufend negative Zahlen von einem globalen Zähler (-1, -2, -3 usw.) zugewiesen. Der Parameter, der den niedrigeren Zeitstempelwert hatte (oder zugewiesen wurde), würde dann durch den anderen ersetzt.

Bei Verwendung eines solchen Ansatzes würden, wenn viele Objektinstanzen wiederholt miteinander verglichen würden, viele der Verweise durch Verweise auf "ältere" Instanzen ersetzt. Abhängig von den Verwendungsmustern kann dies dazu führen, dass die meisten identischen Objektinstanzen ohne Verwendung eines internen Wörterbuchs zusammengeführt werden. Die Anwendung eines solchen Ansatzes mit verschachtelten Objekten würde jedoch erfordern, dass "unveränderliche" Objekte das Mutieren von Verweisen auf verschachtelte Objekte ermöglichen, um auf andere vermeintlich identische verschachtelte Objekte zu verweisen. Dies sollte in Ordnung sein, wenn es sich bei "vermeintlich identischen" Objekten immer um Objekte handelt. Andernfalls kann dies zu bizarrem Fehlverhalten führen.

Antworten auf die Frage(1)

Ihre Antwort auf die Frage