Where can I find good implementation of IDictionary
which uses weak references inside?
Dictionary should be holding only weak references to values and eventually clean up itself of dead references.
Or should I just write it myself?
When a weak reference A is created to an object B, there would be an entry in the hashtable modified or created, whose key would be the pointer to B. "Dirty" - to store a special hash-value with each object, which would be zeroed when the object is destroyed.
A weak reference allows the garbage collector to collect an object while still allowing an application to access the object. If you need the object, you can still obtain a strong reference to it and prevent it from being collected.
Use long weak references only when necessary as the state of the object is unpredictable after finalization. Avoid using weak references to small objects because the pointer itself may be as large or larger. Avoid using weak references as an automatic solution to memory management problems.
The WeakReference is a reference type and so, when you allocate a WeakReference you are allocating an entire object (with a finalizer too) to reference another object. Only that other object will be "weakly referenced". So it is usually not recommended to use WeakReference s to reference small data.
ConditionalWeakTable Class uses weak keys and automatically removes the key/value entry as soon as no other references to a key exist outside the table.
You'll need to write it yourself. It should be relatively straight forward, implementing the IDictionary<T,T>
interface and then storing the actual values as WeakReferences<T>
. You can then check the values on add/select using TryGetTarget
to see if they're still alive.
public class WeakDictionary <TKey,TValue> : IDictionary<TKey,TValue> where TValue : class { private readonly Dictionary<TKey,WeakReference<TValue>> innerDictionary = new Dictionary<TKey,WeakReference<TValue>>(); public TValue Index[ TKey key ] { get { // Use .TryGetTarget instead of .IsAlive and .Target if (this.innerDictionary.TryGetValue(key, out WeakReference<TValue> wf) && wf.TryGetTarget(out TValue value)) { return value; } return null; } } private void Cull() { var deadKeys = this.innerDictionary.Where(kvp => kvp.Value.IsAlive).Select(kvp => kvp.Key).ToList(); foreach (var key in deadKeys) { _ = this.innerDictionary.TryRemove(key); } } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With