2006-12-02

WeakReference woes!

Take a look at the following code

if (myWeakReference.IsAlive)
(myWeakReference.Target as SomeClass).DoSomething();

Do you see the mistake? The WeakReference may return "true" for IsAlive, but because the garbage collector runs within its own thread the value may actually get collected before the next line (because WeakReference.Target does not prevent the GC from collecting the value). I've been using WeakReferences quite a lot recently so I was happy to see that the following changes fixed the occasional NullReferenceException occurencies I had been seeing which were quite difficult to track down!

SomeClass myInstance = (SomeClass)myWeakReference.Target;
if (myInstance != null)
myInstance.DoSomething();

The IsAlive property in my opinion is utterly useless (it is the same implementation as Target). I think MS should just remove it, you could say it would break existing code, but I say it would force people to fix it!

2 comments:

Andy said...

The MSDN documentation clearly explains this problem with IsAlive: "using this property is not recommended unless you are testing only for a false return value".

As this suggests, IsAlive is useful for finding dead references, e.g. if you have a dictionary of weak references, you can go through and easily identify the dead references to be removed using the IsAlive property.

Peter Morris said...

I am not saying it is hard to use once you know about it, I am just saying that it's an easy trap to fall into so I blogged about it.

As for removing IsAlive, I think people would just write code like this anyway so there's no point.

if (weakRef.Target != null)
(weakRef.Target as X).DoSomething();