Weak 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
}