.NET Lazy initialization using Lazy<T>

By Indranil Chatterjee

We often come across objects that consume significant memory, are resource intensive to construct, but at the same time, they are access less frequently. What if we could instantiate them only when they are accessed and that too with callers being transparent of that fact? This code illustrates that using the Lazy<T> class.

Objects often hold references to each other. At times such references point to certain objects that are of large size and consumes significant amount of memory when loaded (or its creation may be resource intensive). Often we find that such references used sparingly. The question that often gets raised is “can we load them as and when they are accessed?”

One common scenario for application of this technique is for Object Relational mapping tools where entities hold references to related entities that are loaded only when they are accessed by the code.

.NET Framework 4.0 provides a class Lazy<T> that allows achieving lazy loading in an easy way. T is the type of the object being initialized. The wrapped object is accessible by the Lazy<T>.Value property. It is initialized the first time Lazy<T>.Value is accessed by the program or Lazy<T>.ToString method is called.

The following code sample illustrates this. The Customer class holds a reference to Lazy<CreditCardDetails>. It also exposes a public property of type CreditCardDetails with a get block that returns the Value property of the lazy instance so that the callers are transparent of the fact that it has been lazily initialized.

The code uses a specific constructor of the Lazy<T> class that allows one to specify a delegate to supply an instance of type T. The code here uses it just to print a console output that can be used to demonstrate when the object gets instantiated.

//Sample code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ParallelProgramming.ConcurrentDataStructures
{
public static class LazyInitializationProgram
{
public static void Main()
{
//This code doesn't instantiate a CreditCardDetails instance
//though it is a field of the Customer class
var customer = new Customer();

DisplayCustomer(customer);
}

private static void DisplayCustomer(Customer customer)
{
Console.WriteLine("Customer name: {0}", customer.Name);
Console.WriteLine("---Card Details---");
//It is this code when a property of CardDetails is accessed, it gets instantiated
//This will print the console output from Lazy<T> constructor
//If you comment this code, you won't see the console output
Console.WriteLine(customer.CardDetails.CardNumber);
}
}

public class Customer
{
public string Name { get; set; }
private Lazy<CreditCardDetails> _cardDetails;

public Customer()
{
Name = "My Customer";
_cardDetails = new Lazy<CreditCardDetails>(() =>
{
//This console output gets printed when the underlying object gets created the first time
Console.WriteLine("Object created when accessed\n");
return new CreditCardDetails();
});
}

public CreditCardDetails CardDetails
{
get
{
return _cardDetails.Value;
}
}
}

public class CreditCardDetails
{
public string CardNumber { get; set; }
public DateTime ExpiryDate { get; set; }

public CreditCardDetails()
{
CardNumber = "xxxx-zzzz-aaaa-bbbb";
ExpiryDate = new DateTime(2013, 12, 31);
}
}
}

.NET Lazy initialization using Lazy<T>  (1226 Views)