Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Lazy Object Initialization with System.Lazy of T class

0.00/5 (No votes)
1 Jul 2013 1  
I explain how to use System.Lazy class with support of lazy initialization of object
  • Download Sample Code
  • Introduction

    The System.Lazy<T> class is a very nice .NET Framework class that supports any object lazy initialization. In this tip, I explain with an example how we can use System.Lazy<T> class for lazy object initialization as well as implement singleton design pattern with the help of System.Lazy<T> class.

    Background

    I am waiting for lazy loading feature in .NET Framework. I thought a popular framework like .NET Framework should support that type of feature. Fortunately, it comes with .NET Framework version 4 or later. In this post, I explain in detail with an appropriate example.

    Using the Code

    At first, I create a Product entity class that has:

    • 2 property members
      • Id
      • Title
    • and 2 static method members
      • GetProductListLazy
      • GetProductList
    public  class  Product
    {
        public long Id { get; set; }
    
        public string Title { get; set; }
    
        public Product()
        {
            Thread.Sleep(5000);
        }
        public  static  IList<Lazy<Product>> GetProductListLazy()
        {
            var product1 = new Lazy<Product>(() => 
            new Product { Id = 1, Title = "Product 1" });
            var product2 = new Lazy<Product>(() => 
            new Product { Id = 2, Title = "Product 2" });
            var product3 = new Lazy<Product>(() => 
            new Product { Id = 3, Title = "Product 3" });
            return new List<Lazy<Product>> 
            {product1, product2, product3};
        }
        public static IList<Product> GetProductList()
        {
            var product1 = new Product 
            { Id = 1, Title = "Product 1" };
            var product2 = new Product 
            { Id = 2, Title = "Product 2" };
            var product3 = new Product 
            { Id = 3, Title = "Product 3" };
            return new List<Product>
            (new[]{product1, product2, product3 });
        }
    }//end Product class 

    GetProductListLazy returns a List of Product object with Lazy Initialization support with the help of System.Lazy<T> class.

    GetProductList returns a List of Product object without any lazy initialization support.

    In my Product class default constructor, I hold code execution for 5 seconds using Thread.Sleep method

    public Product()
    {  
        Thread.Sleep(5000);//5000 millisecond = 5 second
    }   

    Now, I want to print the number of products containing the list in the console. I just call Product.GetProductList static method.

    IList<Product> list = Product.GetProductList();
    Console.WriteLine("Total products in my list: " + list.Count);

    To print result (number of items in the list), it takes 15 seconds.

    Fifteen Seconds

    Why, because it first creates 3 instances of Product class, then adds to the list and returns. Per object creation takes 5 seconds. I explain before I use Thread.Sleep for achieving that.

    On the other hand, if I called Product.GetProductListLazy method...

    IList<Lazy<Product>> list = Product.GetLazyProductList();
    
    Console.WriteLine("Total products in my list: " + list.Count);  

    ...then it prints result (number of items in the list) within a millisecond.

    Wow! I got my desired result!

    If I iterate that list object, then we can understand in run-time when we actually access any of that object's member, that time object is created.

    foreach (Lazy<Product> prod in list)
    { 
        Console.WriteLine(prod.Value.Title);
        Console.WriteLine("---------------");
    } 

    We can also use System.Lazy<T> class to implement Singleton design pattern. If you want to know what is Singleton design pattern, then you can visit:

    Implementation code using System.Lazy<T> class is as follows:

    public sealed class Singleton
    {
        private static readonly Lazy<Singleton> lazy =
            new Lazy<Singleton>(() => new Singleton());
    
        public static Singleton Instance { get { return lazy.Value; } }
    
        private Singleton()
        {
        }
    }  

    Real Life Example

    In real life, many scenarios may found that costly objects need to store in variable/collection and later need to access those when it is actually needed, or sometimes based on dynamic logic, we may or may not be needed those. In those cases, if we do not initialize those objects lazily, then it will effect performance and may face Timeout exception, if it is used in other costly operation/components like:

    • Network
    • Database
    • File IO

    etc. at object creation time.

    Now example would be

    I have Product, Order, Customer class, Customer object hold its list of order object.

    public class Product
    {
        public string ProductCode{get;set;}
        public string ProductTitle{get;set;}    
        public Product()
        {
        }
    }
    public class Order
    {
        public long OrderId{get;set;}
        public DateTime OrderDateTime{get;set;}
        public IList<Product> OrderedProductList{get;set;}
        public Order()
        {
        }
    }
    public class Customer
    {
        public long CustomerId{get;set;}
        public string FirstName{get;set;}
        public string LastName{get;set;}    
        public IList<Order> OrderList{get;set;}
        
        public Customer()
        {
        }
    }    
    public class CustomerRepository
    {
        public CustomerRepository()
        {
        }    
        public Customer FindCustomer(long customerId)
        {
            //Need to Fetch data from database and populate complete
            //Customer object including List of Orders that customer give
        }
    }

    When our CustomerRepository fetch Customer based on customerId it fetches all customer related data incuding its order collection. So Customer object fetch from database is costly operation. Suppose requirement like:

    • Need to show customer full name in a web page.

    But in code base i need to fetch a complete Customer object including its relational objects like (Order, Order related to Product) etc. But in another scenario we may need to fulfill other requirement

    • Need to show Customer Name with his total order quantity.

    So repository class should return a complete Customer object so that we need to fulfill our requirements from a single point. But again if carefully read first requirement, where only need to show customer full name, it actually kills some performance due to population of order collection. If we can avoid that then this operation will be more faster. In that case we can use System.Lazy<T> class. in that case Customer class looks like:

    public class Customer
    {
        public long CustomerId{get;set;}
        public string FirstName{get;set;}
        public string LastName{get;set;}    
        public IList<Lazy<Order>> OrderList{get;set;}
        
        public Customer()
        {
        }
    }

    When we access Order collection of Customer object that time it populate that list otherwise not. If you explore Object Relational Mapper (ORM) component like NHibernet or some others, you will find that those components follow the lazy initialization stratify. Actually they offer 2 process to load associated objects.

    1. Eager Loading: It loads associate objects at first time.
    2. Lazy Loading: It loads associate objects on demand basis.

    Conclusion

    For the performance point of view lazy initialization is a performance optimization where you differ expensive object creation until just before you need it. The key reason for doing this is that you can avoid creating object completely if you never need it. Actually lazy initialization is delaying initialization until a object is used.

    I am really a fan of System.Lazy<T> class and hope everyone loves it and also thank to the .NET team for the nice feature.

    I have attached a code sample with this tip. To create that sample, I used Visual Studio 2012 with .NET Framework 4.5 version.

    References

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here