Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

LazyWeakReference

0.00/5 (No votes)
10 Dec 2012 1  
A simple class for implementing Lazy Phoenix-like weak reference.

Introduction

This tip presents a small and useful class for having a weak reference that reconstructs itself if needed.

Using the code 

Consider the code below:

BigObject someBigObject = new SomeBigObject();
WeakReference aReference = new WeakReference(someBigObject);
//...
//somewhere else, where someBigObject variable is not accessible any more:
if (aReference.IsAlive == true)
{
 //OK, work with it
}
else
{
 //react
}

For those who have worked with weak references this code is quite familiar. Sometimes the action that should be done about weak reference is known - in my case it's often reinitializing the object back to life. Just consider the following code to see what I got:

[Serializable]
public class LazyWeakReference<T>
     where T : class
{
    WeakReference reference;
    Func<T> constructor = null;
    private int reinitializingCounter = 0;

    public LazyWeakReference(T anObject, Func<T> aConstructor = null)
    {
        reference = new WeakReference(anObject);
        constructor = aConstructor;
    }

    public int Reinitialized { get { return reinitializingCounter; } }

    public T Target
    {
        get
        {
            object target = reference.Target;
            if (target == null)
            {
                if (constructor == null) return null;
                T newObject = constructor();
                reinitializingCounter++;
                reference = new WeakReference(newObject);
                return newObject;
            }
            return (T)target;
        }
    }

}

class Program
{

    public static void Main(string[] args)
    {
        LazyWeakReference<StringBuilder> builder = 
          new LazyWeakReference<StringBuilder>(
          new StringBuilder("A builder"), () => 
          new StringBuilder("Acopy"));
        StringBuilder aTarget = builder.Target;
        aTarget = null;
        GC.Collect();
        Console.WriteLine("Reinitialized {0} times",builder.Reinitialized);
        aTarget = builder.Target;
        aTarget = null;
        GC.Collect();
        Console.WriteLine("Reinitialized {0} times", builder.Reinitialized);
        aTarget = builder.Target;
        aTarget = null;
        GC.Collect();
        Console.WriteLine("Reinitialized {0} times", builder.Reinitialized);
        aTarget = builder.Target;
        aTarget = null;
        Console.WriteLine("Reinitialized {0} times", builder.Reinitialized);
        Console.ReadKey();
    }
}

The output is shown below:

Reinitialized 0 times
Reinitialized 1 times
Reinitialized 2 times
Reinitialized 3 times

Points of Interest 

There is no thread-safety issue in this code. You could add it. This functionality is enough for my needs.

History

  • December 10, 2012 - First published.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here