Using C# 4 to implement lazy initialization
Sometimes we wish to improve performance and improve memory usage by making sure the Object we create and initialize is really needed. A couple of scenarios that we might thing of are:
Up until now days we had to implement this laziness by ourselves. Now we can use the Lazy<T> within .NET 4.
Her are some samples and expiations from MSDN:
To define a lazy-initialized type, for example, MyType, use Lazy<MyType> (Lazy(Of MyType) in Visual Basic), as shown in the following example. If no delegate is passed in the Lazy<T> constructor, the wrapped type is created by using ActivatorCreateInstance() when the value property is first accessed. If the type does not have a default constructor, a run-time exception is thrown.
// Initialize by invoking a specific constructor on Order when Value
// property is accessed
Lazy<Orders> _orders = new Lazy<Orders>(() => new Orders(100));
You can also pass a delegate in the Lazy<T> constructor that invokes a specific constructor overload on the wrapped type at creation time, and perform any other initialization steps that are required, as shown in the following example.
// Initialize by invoking a specific constructor on Order when Value
// property is accessed
Lazy<Orders> _orders = new Lazy<Orders>(() => new Orders(100));
After the Lazy object is created, no instance of Orders is created until the Value property of the Lazy variable is accessed for the first time. On first access, the wrapped type is created and returned, and stored for any future access.
// We need to create the array only if displayOrders is true
if (displayOrders == true)
{
DisplayOrders(_orders.Value.OrderData);
}
else
{
// Don't waste resources getting order data.
}
Thread–safe Initialization
Some Lazy<T> constructor overloads have a Boolean parameter named isThreadSafe that is used to specify whether the Value property will be accessed from multiple threads. If you intend to access the property from just one thread, pass in false to obtain a modest performance benefit. If you intend to access the property from multiple threads, pass in true to instruct the Lazy instance to correctly handle race conditions in which one thread throws an exception at initialization time. If you use a constructor that does not have the isThreadSafe parameter, the value defaults to true.
In multi-threaded scenarios, the first thread to access the Value property initializes it for all subsequent accesses on all threads, and all threads share the same data. Therefore, it does not matter which thread initializes the object, and race conditions are benign. If the first thread to initialize Value causes an exception to be thrown, that same exception will be thrown for all subsequent accesses of Value. It is not possible for one thread to raise an exception and another to initialize the object. The following example shows that the same Lazy<int> instance has the same value for three separate threads.
// Initialize the integer to the managed thread id of the
// first thread that accesses the Value property.
Lazy<int> number = new Lazy<int>(() => Thread.CurrentThread.ManagedThreadId);
Thread t1 = new Thread(() => Console.WriteLine("number on t1 = {0} ThreadID = {1}",
number.Value,
Thread.CurrentThread.ManagedThreadId));
t1.Start();
Thread t2 = new Thread(() => Console.WriteLine("number on t2 = {0} ThreadID = {1}",
number.Value,
Thread.CurrentThread.ManagedThreadId));
t2.Start();
Thread t3 = new Thread(() => Console.WriteLine("number on t3 = {0} ThreadID = {1}",
number.Value,
Thread.CurrentThread.ManagedThreadId));
t3.Start();
//Ensure that thread IDs are not recycled if the
//first thread completes before the last one starts.
t1.Join();
t2.Join();
t3.Join();
Enjoy :-)