Lazy loading
Lazy loading is a concept where we delay the loading of the object until the point where we need it. Putting in simple words, on demand object loading rather than loading objects unnecessarily.
Lazy Initialization
Lazy initialization of an object means that its creation is deferred until it is first used. Primary use of lazy initialization is to
- Improve performance
- Avoid wasteful computation
- Reduce memory requirements
Imagine the following scenario. You have a customer object in memory that has an Orders property that contains an array of Order objects. If a user never asks to display the Orders or use the data in it, then there is no particular reason to use system memory to create it. To avoid wasting system resources when the object is not used you can declare Orders object for lazy initialization.
Thread-Safe Initialization
By default Lazy objects are thread-safe. In multi-threaded scenarios the first thread to access the Value property of a thread-safe Lazy object initializes it for all subsequent access on all thread and all threads share the same data.
Lazy Initialization example
To define a lazy initialized type use Lazy. If no delegate is passed in the Lazy constructor the wrapped type is created by using Activator.CreateInstance when the value property is first accessed. If the type does not have a parameterless constructor, a run-time exception is thrown. In the following example we are going to create a Customer object containing an Orders property using Lazy initialization.
public class Customer
{
public Guid Id { get; set; }
public string Name { get; set; }
private readonly Lazy<Orders> Orders;
public Customer()
{
Orders = new Lazy<Orders>(GetMockOrders);
}
public Orders CustomerOrders => Orders?.Value;
// Setup Orders data
private static Orders GetMockOrders(){}
// Setup Order list data
private static IEnumerable<Order> GetMockOrder(){}
}
We are going to run the above in a console app and add a break point on line 12 before assign value on the orders
variable.
If we now look at the Debug Output we can observe that orderList
in customerOrders
contains no Value. That is because of lazy loading orderList
not yet been called.
If we step over the break point and continue we can see some interesting things.
First of all the Value of orderList
is now containing a list of orders and expanding that list we can see the populated properties of that value. Second we can see that now the isValueCreated
is equal to true, this means that the instance has been created.
To sum things up, lazy loading is a great optimization technique that can improve performance of our application and save memory resources.
You can download the code from GitHub