WeakRefrence als Key einer Dictionary
-
Hallo µ
Ja ohne Comparer funktioniert das nicht. Das hatte ich auch schon getestet
Da werde ich deine Lösung gleich mal testen. Danke
-
Auf WeakReference angewendet sollte dies doch so in etwa aussehen.
Irgendwas ist aber noch falsch.
public class ContainerClass { private readonly Dictionary<WeakReference, WeakReference> Container = new Dictionary<WeakReference, WeakReference>(); public void Add(MyKeyClass key, MyValueClass value) { Container.Add(new WeakReference(key), new WeakReference(value)); } public MyValueClass GetViewModel(MyKeyClass key) { var index = new WeakReference(key); var value = Container[index].Target as MyValueClass; //hier gibt es eine Exception return value ; } } class Comparer : IEqualityComparer<WeakReference> { public bool Equals(WeakReference x, WeakReference y) { return x.Target == y.Target; } }
-
Vieleicht etwas genauer:
KeyNotFoundException
In die Methode Comparer.Equals springt der Debugger nie rein.
-
Obiges war der allgemeine Fall, da mir sowas auch schonmal untergekommen ist.
Aber: Durch WeakReference hast Du nochmals einen Sonderfall.
Ich schätze die Referenzen auf Deine MyKeyClass-Objekte behältst Du nicht vor. Sonst wären die WeakReferencen ja sinnlos.
Woher kommen also die MyKeyClass-Referenzen für die spätere Abfrage des Dictionary?
Falls dahinter neue Objekte stecken, muss Operator== (oder ein anderes Vergleichskonzept) entsprechend überladen werden, damit das in der Equals-Methode des Comparers funktioniert.Alternative: Du hantierst überall nur mit den WeakReference-Wrappern und behältst deren Referenzen auch vor. Dann kannst Du dir die ganze Comparer-Geschichte sparen, da ein uns dasselbe Key-Objekt (WeakReference) dem Einfügen wie auch dem Abfragen dient.
Was willst du mit diesem merkwürdigen Konstrukt erreichen?
Dictionary<WeakReference, WeakReference>
-
y-vonne schrieb:
Auf WeakReference angewendet sollte dies doch so in etwa aussehen.
Irgendwas ist aber noch falsch.
Das Dictionary verwendet den Comparer garnicht -> Als Konstrutkorparameter übergeben. Außerdem fehlt GetHashCode im Comparer.
-
Das ist ein ganz schlechte Idee!
Was passiert, wenn im
Dictionary
zwei Referenzen aufnull
gehen? Dann hast du zweimalnull
als Key, obwohlnull
als Keywert und zweimal derselbe Key nicht von der Klasse unterstützt werden! Du vernichtest damit die Invariante der Klasse.Grüssli
-
Oh,
GetHashCode habe ich vergessen hier reinzukopieren. Ist im richtigen Code drin.
Richtig und Comparer habe tatsächlich vergessen.So nun aber:
public class ContainerClass { private readonly Dictionary<WeakReference, WeakReference> Container = new Dictionary<WeakReference, WeakReference>(); public void Add(MyKeyClass key, MyValueClass value) { Container.Add(new WeakReference(key), new WeakReference(value)); } public MyValueClass GetViewModel(MyKeyClass key) { var index = new WeakReference(key); var value = Container[index].Target as MyValueClass; //hier gibt es eine Exception return value ; } } class Comparer : IEqualityComparer<WeakReference> { public bool Equals(WeakReference x, WeakReference y) { return x.Target == y.Target; } public int GetHashCode(WeakReference obj) { return obj.GetHashCode(); } }
Aber irgendwie bekomme ich nun immer noch den selben Fehler.
-
Hallo Dravere
Dein Beitrag habe ich zu spät gesehen.
Ok das ist ein Argument. Ist es dann nicht irgendwie mögich. Wenn ein Eintrag auf null geht diesen zu löschen?
-
Mist und new Comparer schon wieder vergessen !!!
private readonly Dictionary<WeakReference, WeakReference> Container = new Dictionary<WeakReference, WeakReference>(new Comparer());
-
Dravere schrieb:
Das ist ein ganz schlechte Idee!
Was passiert, wenn im
Dictionary
zwei Referenzen aufnull
gehen? Dann hast du zweimalnull
als Key, obwohlnull
als Keywert und zweimal derselbe Key nicht von der Klasse unterstützt werden! Du vernichtest damit die Invariante der Klasse.Grüssli
Auf WeakReference ist das nicht anwendbar.Nochmal an den OP: Warum muss der Key "Weak" sein?
-
Ich dachte halt wenn das Key Objekt ausserhalb der dictionary nicht mehr verwendet wird kann es gelöscht werden.
Meine Intention war allerdings dass der Eintrag dann komplett aus der Dictionray verschwindet. Und dachte nicht daran dass nur die Reference auf null geht
-
y-vonne schrieb:
Ich dachte halt wenn das Key Objekt ausserhalb der dictionary nicht mehr verwendet wird kann es gelöscht werden.
Meine Intention war allerdings dass der Eintrag dann komplett aus der Dictionray verschwindet. Und dachte nicht daran dass nur die Reference auf null geht
Das wäre zwar über einen Finalizer möglich, aber nicht zu empfehlen. Du solltest lieber das Design deiner Applikation überdenken.
In C# räumt der GC für einem zwar den Speicher auf, aber man muss trotzdem selber die Objekte aufräumen. Daran kommt man nicht vorbei.
Grüssli