- RISE FROM THE ASHES – Sanjib Nandi - November 1, 2021
- साथ में मेरे दोस्त खड़े थे - August 1, 2021
- BenchmarkDotNet: Advanced Features - June 20, 2021
Performance has always been overhead for all the programmers. They try to optimize the code using various techniques. Like Lazy Loading, Lazy instantiating is also a great candidate, and with .NET 4.0 implementation of Lazy<T>
Being lazy is not encouraged and everyone is expected to become proactive but the programming world behaves differently. Here, we love to get something only when it is needed.
What is this Lazy<T>?
This is the .NET framework implementation of lazy instantiation. That means instantiating an object only when it is needed. For this, we normally use large objects or resource extensive objects.
This is thread-safe for creation i.e. when an object is instantiated in a multithreaded setup, using Lazy<T> will ensure only ONE single instance of the object and it is created by one thread ONLY.
Please make sure, that only object creation is thread-safe, if you need to use this object from different threads, it will need locking to avoid a race condition.
Use Case
When it is very expensive to create an object or we know in advance that dependent objects will NOT be needed all the time, we can use this.
Scenario # 1 –for my Insurance, I enter my insurance ID, but at this point, I may navigate to renew, cancel, file a claim, etc. so in this condition I may not need to load my complete insurance history unless I ask for it.
Scenario # 2 – Using Singleton class. I will explain this code in the next section of this article and where we will know more about this.
How to use it?
Lazy<T> comes with many constructors and more options but will restrict this article to the most common scenario.
Lazy<LargeObject> lazyLargeObject = new Lazy<LargeObject>(GetInsuranceHistory);
static LargeObject GetInsuranceHistory ()
{
// Perform operation here.
return large;
}
Another way of instantiating using delegates –
Lazy<LargeObject> lazyLargeObject = new Lazy<LargeObject>(()=>
{
// Perform operation here.
return large;
});
One real-life Scenario and Code Explanation–
As promised, here is singleton class example and in the following section, I am going to explain –
1. Scenario –
In this code, I want to cache some master data and I will be instantiating them only when it is needed for the first time and once, they are instantiated, it shall not make any operation to instantiate again. To insert delay in the process to imitate the long process.
2. Code Flow –
With the lazy instantiation of the class, we are passing GetData method as a parameter. GetData method fetches records from the database/calculating value and assigns values to the local private variables.
public sealed class DataCache
{
private static Lazy<DataCache> local = new Lazy<DataCache>(GetData);
private List<string> _names = null;
public static List<string> Names
{
get
{
return local.Value._names;
}
}
private static DataCache GetData()
{
DataCache cache = new DataCache();
cache._names = Employees.GetNames();
Console.WriteLine("GetData Method Called");
return cache;
}
}
public class Employees
{
public static List<string> GetNames()
{
System.Threading.Thread.Sleep(2000);
return new List<string>()
{"Atul", "Ramesh", "Mahesh", "Devesh", "Ajay" };
}
}
Lazy is instantiated ONLY when Value is called, and in this case, Value is called from the static property.
var x = DataCache.Names;
Now, to access the value of cache values, we need to call the property from external agent.
3. Ensure only One instance is created
For that, in GetData I will print the message. In the client application, I will call this 10 times but as output, we will see only ONE message printed in the console.
static void Main(string[] args)
{
for (int i = 0; i < 10; i++)
{
var x = DataCache.Names;
}
Console.ReadLine();
}
This diagram shows the flow of control using Lazy<T>
I hope this example gives you a fair idea of Lazy<T> and code is available here to play around.