I understand what System.WeakReference does, but what I can't seem to grasp is a practical example of what it might be useful for. The class itself seems to me to be, well, a hack. It seems to me that there are other, better means of solving a problem where a WeakReference is used in examples I've seen. What's the canonical example of where you've really got to use a WeakReference? Aren't we trying to get farther away from this type of behavior and use of this class?
Weak reference objects, which do not prevent their referents from being made finalizable, finalized, and then reclaimed. Weak references are most often used to implement canonicalizing mappings. Suppose that the garbage collector determines at a certain point in time that an object is weakly reachable.
As stated by Java documentation, weak references are most often used to implement canonicalizing mappings. A mapping is called canonicalized if it holds only one instance of a particular value. Rather than creating a new object, it looks up the existing one in the mapping and uses it.
One useful example is the guys who run DB4O object oriented database. There, WeakReferences are used as a kind of light cache: it will keep your objects in memory only as long as your application does, allowing you to put a real cache on top.
Another use would be in the implementation of weak event handlers. Currently, one big source of memory leaks in .NET applications is forgetting to remove event handlers. E.g.
public MyForm() { MyApplication.Foo += someHandler; }
See the problem? In the above snippet, MyForm will be kept alive in memory forever as long as MyApplication is alive in memory. Create 10 MyForms, close them all, your 10 MyForms will still be in memory, kept alive by the event handler.
Enter WeakReference. You can build a weak event handler using WeakReferences so that someHandler is a weak event handler to MyApplication.Foo, thus fixing your memory leaks!
This isn't just theory. Dustin Campbell from the DidItWith.NET blog posted an implementation of weak event handlers using System.WeakReference.
I use it to implement a cache where unused entries are automatically garbage collected:
class Cache<TKey,TValue> : IEnumerable<KeyValuePair<TKey,TValue>> { Dictionary<TKey,WeakReference> dict = new Dictionary<TKey,WeakReference>(); public TValue this[TKey key] { get {lock(dict){ return getInternal(key);}} set {lock(dict){ setInteral(key,value);}} } void setInteral(TKey key, TValue val) { if (dict.ContainsKey(key)) dict[key].Target = val; else dict.Add(key,new WeakReference(val)); } public void Clear() { dict.Clear(); } /// <summary>Removes any dead weak references</summary> /// <returns>The number of cleaned-up weak references</returns> public int CleanUp() { List<TKey> toRemove = new List<TKey>(dict.Count); foreach(KeyValuePair<TKey,WeakReference> kv in dict) { if (!kv.Value.IsAlive) toRemove.Add(kv.Key); } foreach (TKey k in toRemove) dict.Remove(k); return toRemove.Count; } public bool Contains(string key) { lock (dict) { return containsInternal(key); } } bool containsInternal(TKey key) { return (dict.ContainsKey(key) && dict[key].IsAlive); } public bool Exists(Predicate<TValue> match) { if (match==null) throw new ArgumentNullException("match"); lock (dict) { foreach (WeakReference weakref in dict.Values) { if ( weakref.IsAlive && match((TValue) weakref.Target)) return true; } } return false; } /* ... */ }
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