Lazy initialization in .NET 4 – Lazy<T>

A very common pattern in programming is the Lazy Initialization Pattern.  Version 4 of the .NET Framework makes using this pattern very, very easy.

Version 4 of the .NET Framework is adding System.Lazy<T> directly to the mscorlib assembly in the framework.  This class provides a very simple, consistent way to provide thread safe, lazy initialization of expensive objects, as well as being able to query whether the object has been created without accidentally constructing your object.

Usage is very clean and flexible.  There are four construction options, two which use the default type constructor, and two which take a Func<T>.  The constructors also include an optional boolean parameter which specifies whether construction and access should be thread safe.  By default, the Lazy<T> type uses locking for access to provide a thread safe mechanism, but this can be avoided for performance if you can guarantee usage from a single thread.  The parameter here is a Func<T> – basically, any method that will construct and return our instance of the class.

You define your object inside of the Lazy class, and either use the default constructor or provide a delegate of type Func<T> to initialize the object.  For example, say we have a class called MessageClass that takes a string parameter in its constructor:

class MessageClass
{
    public string Message { get; set; }

    public MessageClass(string message)
    {
        this.Message = message;
        Console.WriteLine("  ***  MessageClass constructed [{0}]", message);
    }
}

We can declare and use this simply by creating a lambda to pass in our string parameter:

Lazy<MessageClass> someInstance = new Lazy<MessageClass>(
        () => new MessageClass("The message")
    );

We then have access to the IsValueCreated property, which tells us whether or not the instance has been created, as well as the Value property, which will construct and return our actual instance on demand.

Here’s an example showing a complete program using the MessageClass above, demonstrating the usage of Lazy<T>:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Declaring instances");
        MessageClass instance1 = new MessageClass("instance1");
        Lazy<MessageClass> instance2 = new Lazy<MessageClass>(() => new MessageClass("instance2"));
        Console.WriteLine("Instances declared");
        Console.WriteLine();
        Console.WriteLine("instance2's MessageClass initialized:  {0}", instance2.IsValueCreated);
        Console.WriteLine(); 

        Console.WriteLine("instance1.Message: {0}", instance1.Message);
        Console.WriteLine("instance2.Message: {0}", instance2.Value.Message);
        Console.WriteLine(); 
        Console.WriteLine("instance2's MessageClass initialized:  {0}", instance2.IsValueCreated);
        Console.ReadKey();
    }
}

The above program, when run, prints out:

Declaring instances
  ***  MessageClass constructed [instance1]
Instances declared

instance2's MessageClass initialized:  False

instance1.Message: instance1
  ***  MessageClass constructed [instance2]
instance2.Message: instance2

instance2's MessageClass initialized:  True

Notice how simple this becomes now.  All you do is use Lazy<MyClass> instead of MyClass, optionally provide a delegate for construction, and use object.Value to access!  The type automatically delayed our construction until the first type we accessed it (instance2.Value.Message).

About Reed
Reed Copsey, Jr. - http://www.reedcopsey.com - http://twitter.com/ReedCopsey

Comments

3 Responses to “Lazy initialization in .NET 4 – Lazy<T>”
  1. Ian Randall says:

    Thanks Reed! I heard about this class on ‘Better Know Framework’ on dot net rocks, and your blog was the first Google hit! Thanks for explaining this so well – keep up the good work :)

    Ian Randall, Auckland

  2. Reed says:

    Thanks for the feedback, Ian!

Trackbacks

Check out what others are saying about this post...
  1. [...] Reed Copsey Jr. blogged about this and he gave me some pointers on my initial implementation. Here I’ve sealed the class and made the constructor private, rather than protected. Usually I’m not a big fan of sealing classes but in [...]



Speak Your Mind

Tell us what you're thinking...
and oh, if you want a pic to show with your comment, go get a gravatar!