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 h
There are two reasons why you would use WeakReference
.
Instead of global objects declared as static: Global objects are declared as static fields and static fields cannot be GC'ed (garbage-collected) until the AppDomain
is GC'ed. So you risk out-of-memory exceptions. Instead, we can wrap the global object in a WeakReference
. Even though the WeakReference
itself is declared static, the object it points to will be GC'ed when memory is low.
Basically, use wrStaticObject
instead of staticObject
.
class ThingsWrapper {
//private static object staticObject = new object();
private static WeakReference wrStaticObject
= new WeakReference(new object());
}
Simple app to prove that static object is garbage-collected when AppDomain is.
class StaticGarbageTest
{
public static void Main1()
{
var s = new ThingsWrapper();
s = null;
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
class ThingsWrapper
{
private static Thing staticThing = new Thing("staticThing");
private Thing privateThing = new Thing("privateThing");
~ThingsWrapper()
{ Console.WriteLine("~ThingsWrapper"); }
}
class Thing
{
protected string name;
public Thing(string name) {
this.name = name;
Console.WriteLine("Thing() " + name);
}
public override string ToString() { return name; }
~Thing() { Console.WriteLine("~Thing() " + name); }
}
Note from the output below staticThing
is GC'ed at the very end even after ThingsWrapper
is - i.e. GC'ed when AppDomain
is GC'ed.
Thing() staticThing
Thing() privateThing
~Thing() privateThing
~ThingsWrapper
~Thing() staticThing
Instead we can wrap Thing
in a WeakReference
. As wrStaticThing
can be GC'ed, we'll need a lazy-loaded method which I've left out for brevity.
class WeakReferenceTest
{
public static void Main1()
{
var s = new WeakReferenceThing();
s = null;
GC.Collect();
GC.WaitForPendingFinalizers();
if (WeakReferenceThing.wrStaticThing.IsAlive)
Console.WriteLine("WeakReference: {0}",
(Thing)WeakReferenceThing.wrStaticThing.Target);
else
Console.WriteLine("WeakReference is dead.");
}
}
class WeakReferenceThing
{
public static WeakReference wrStaticThing;
static WeakReferenceThing()
{ wrStaticThing = new WeakReference(new Thing("wrStaticThing")); }
~WeakReferenceThing()
{ Console.WriteLine("~WeakReferenceThing"); }
//lazy-loaded method to new Thing
}
Note from output below that wrStaticThing
is GC'ed when GC thread is invoked.
Thing() wrStaticThing
~Thing() wrStaticThing
~WeakReferenceThing
WeakReference is dead.
For objects that are time-consuming to initialize: You do not want objects that are time-consusming to init to be GC'ed. You can either keep a static reference to avoid that (with cons from above point) or use WeakReference
.