Leveraging Delayed Instantiation with Lazy<T>

Being lazy doesn't refer to being lazy in life, but being lazy about the creation or instantiation of objects in our code. Sometimes, creation of an object is very costly. Now, when we say "costly", we are not talking about money. Rather, we are talking about the memory consumed in the process and by the object itself.

Consider a component A that uses a service B. It is very likely for class A to have methods that do not use the object of class B. Please refer the code below,
  1. public class A  
  2. {  
  3.     private B _b;  
  4.     public A(B b)  
  5.     {  
  6.         _b = b;  
  7.     }  
  8.   
  9.     public void MethodOne()   
  10.     {  
  11.         _b.ClassBMethod();  
  12.     }  
  13.   
  14.     public void MethodTwo()  
  15.     {  
  16.         // does not use _b  
  17.     }  
  18.   
  19.     public void MethodThree()  
  20.     {  
  21.         // does not use _b  
  22.     }  
  23. }  
  24.   
  25. public class B   
  26. {  
  27.     public void ClassBMethod() { //do something }  
  28. }  
 If we are using class A for MethodTwo and MethodThree only, we will overburden the runtime to instantiate B, which, in fact, will never be used. So, how do we handle it?

Using Lazy <T>

When we inject a dependency as Lazy<T>, we delay the construction of part of the object graph either for functional or performance reasons. Moreover, Lazy<T> will be automatically injected, as long as T is registered with the DI container.

Lazy<T> represents a value that is initialized the first time it is accessed. Therefore, the above code can be written as the following.
  1. public class A  
  2. {  
  3.     private Lazy<B> _b;  
  4.     public A(Lazy<B> b)  
  5.     {  
  6.         _b = b;  
  7.     }  
  8.   
  9.     public void MethodOne()   
  10.     {  
  11.         _b.Value.ClassBMethod();  
  12.     }  
  13.   
  14.     public void MethodTwo()  
  15.     {  
  16.         // does not use _b  
  17.     }  
  18.   
  19.     public void MethodThree()  
  20.     {  
  21.         // does not use _b  
  22.     }  
  23. }  
As a result, class B object will be instantiated only when we access it for the first time. This is to say, that the object instantiation takes place at line _b.Value.ClassBMethod(); and the object will remain in memory for any further use. Not to mention, if we create an object of class A and call the methods MethodTwo and MethodThree, class B will not be instantiated.

This is certainly one way of using lazy initialization. We can also use Lazy<T,TMetadata>. It works exactly the same way as Lazy<T>, but adds a Metadata property that can be used to get information about the value before it is instantiated. To know more about it, please stay tuned. :)

Related Articles