Use Lazy Initialization to Delay Object Instantiation
It is a common practice to declare object variables as the class members and
initialize them in the constructor of the class. At times, however, you need to
delay the object instantiation until its first use. One way to achieve such an
deferred object instantiation is to write custom code that implements Lazy Load
pattern. An easy alternative is to use .NET framework's inbuilt lazy
initialization feature. To that end this article explains the later approach.
Suppose you wish to create Customer class as shown below:
public class Customer
{
public string CustoemrID { get; set; }
public string CompanyName { get; set; }
public string ContactName { get; set; }
public string Country { get; set; }
public List<Order> Orders { get; }
public List<Product> Products { get; }
public Customer()
{
this.Orders = new List<Order>();
this.Products = new List<Product>();
//fill Orders and Products here
//through some lengthy processing
}
}
The Customer class consists of six properties - CustomerID, CompanyName,
ContactName, Country, Orders and Products. The first four properties are quite
straightforward. The Orders property holds a List of Order objects representing
orders placed by a customer so far. The Products property holds a list of
Product objects representing a List of unique products ordered by a customer so
far. These properties are initialized and filled in the constructor of the
Customer class.
Now further assume that the Customer class is being used in three modules -
Contact manager module, Order processing and tracking module and Product
tracking module. When used in the contact manager module the Orders and Products
properties won't play any role. Similarly order processing module may not need
the Products property. Thus Orders and Products properties may waste the
resources. Moreover, initializing these properties in the constructor might also
cause performance penalty to the instantiation of the Customer class. That is
where lazy loading comes into the picture.
The .NET framework's System.Lazy class provides an easy way to implement lazy
loading in your applications. The Lazy<T> class wraps an object and instantiates
it only when an object is accessed. This way there won't be any wastage of
resources since an object is being created only if it is needed. Moreover, it
frees the constructor from the lengthy initialization improving the
instantiation time.
Let's rewrite the Customer class using the Lazy<T> class.
public class CustomerLazy
{
public string CustoemrID { get; set; }
public string CompanyName { get; set; }
public string ContactName { get; set; }
public string Country { get; set; }
private Lazy<List<Order>> lazyOrders =
new Lazy<List<Order>>(() => {
List<Order> orders = new List<Order>();
//lengthy processing that fills Orders
return orders;
});
private Lazy<List<Product>> lazyProducts =
new Lazy<List<Product>>(() => {
List<Product> products = new List<Product>();
//lengthy processing that fills Products
return products;
});
public List<Order> Orders
{
get
{
return lazyOrders.Value;
}
}
public List<Product> Products
{
get
{
return lazyProducts.Value;
}
}
}
Notice the code marked in bold letters. The code declares two private member
variables - lazyOrders and lazyProducts - at the top. These Lazy<T> objects wrap
List<Order> and List<Product> respectively. Moreover, the code that fills the
order and product lists is moved inside a delegate function passed to the
constructor of the Lazy class.
The Orders and Products properties are then declared with property getters.
The property getters uses the Value property of Lazy<T> class to get an instance
of the List<Order> and List<Product>. These instances are created when the
getter properties are accessed for the first time. While creating these
instances the code inside the delegate function is also executed. Thus the
object instantiation is delayed until an instance is actually needed.
If you don't wish to execute any code during the object creation you can use
the Lazy<T> as follows:
private Lazy<List<Order>> lazyOrders = new Lazy<List<Order>>();
private Lazy<List<Product>> lazyProducts = new Lazy<List<Product>>();
In this case List<Order> and List<Product> are created by Lazy<T> for you
when Value is accessed for the first time.