Weak References
suggest changeWeak references are… references, to other objects (aka “targets”), but “weak” as they do not prevent those objects from being garbage-collected. In other words, weak references do not count when the Garbage Collector evaluates objects as “live” or “dead”.
The following code:
var weak = new WeakReference<FinalizableObject>(new FinalizableObject()); GC.Collect();
Produces the output:
<namespace>.FinalizableObject initialized <namespace>.FinalizableObject finalized
The object is freed from the managed heap despite being referenced by the WeakReference variable (still in scope when the Garbage collector was invoked).
Consequence #1: at any time, it is unsafe to assume whether a WeakReference target is still allocated on the managed heap or not.
Consequence #2: whenever a program needs to access the target of a Weakreference, code should be provided for both cases, of the target being still allocated or not. The method to access the target is TryGetTarget:
var target = new object(); // Any object will do as target var weak = new WeakReference<object>(target); // Create weak reference target = null; // Drop strong reference to the target // ... Many things may happen in-between // Check whether the target is still available if(weak.TryGetTarget(out target)) { // Use re-initialized target variable // To do whatever the target is needed for } else { // Do something when there is no more target object // The target variable value should not be used here }
The generic version of WeakReference is available since .Net 4.5. All framework versions provide a non-generic, untyped version that is built in the same way and checked as follows:
var target = new object(); // Any object will do as target var weak = new WeakReference(target); // Create weak reference target = null; // Drop strong reference to the target // ... Many things may happen in-between // Check whether the target is still available if (weak.IsAlive) { target = weak.Target; // Use re-initialized target variable // To do whatever the target is needed for } else { // Do something when there is no more target object // The target variable value should not be used here }