Ryan Hoffman

Thoughts from a .NET obsessed software architect and developer.

.NET 4 Hidden Gem: System.Lazy

I’ve been using .NET 4.0 at work since Beta 1. Yes, it’s been about a year+ now. Now that .NET 4 / VS2010 has RTM’ed, lots of developers are grabbing the new bits. Because of this, I’m going to make a series of posts about some new hidden gemss (aka features I really like :-D) in .NET 4.

One really cool new class in the BCL is System.Lazy. The beauty of this object is it allows you to define complex or potentially long running initialization code for an object and ensure it only executes once, which it handles automatically. The lazy object allows you to write initialization code for an object, which is passed to it in as a Func<T>. Here’s a simple example of how to create a new Lazy object:

1
var lazy = new Lazy<string>(() => LongRunningMethodGetsString());

Lazy provides two properties, IsValueCreated and Value. You use IsValueCreated (which returns a bool) to determine if the object has been initialized. The Value property returns a type T, which returns the object that you create in your initializer code. When you first create a new Lazy object, IsValueCreated is false, until you call the Value property. Your initializer code only runs once, and the Lazy object will always return the result when you call Value.

I have a nice little pattern around the lazy object, which wraps a read-only property around a private lazy object. This makes it easier for consumers of your class to use a lazy object that you are using, by just returning T instead of Lazy<T>.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Awesomeness
{
    private Lazy<AwesomeObject> _ourAwesomeObject = new Lazy<AwesomeObject>(() =>
    {
        var awesomeObject = new AwesomeObject();
        //do stuff here to build your awesomeObject
        return awesomeObject;
    });

    public AwesomeObject OurAwesomeObject
    {
        get { return _ourAwesomeObject.Value; }
    }
}

One last word of advice when using Lazy: always make sure that your initializer does not throwan exception. If it throws an exception (or an unhandled exception occurs), then any calls to the Value property will aways re-throw this exception. In the case that your initializer could throw an exception, either wrap it in a try block, or just don’t use the Lazy object all together (perhaps by keeping a private field with the initialized value and checking to see if it is null).

Comments