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).
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
Thanks for the feedback, Ian!