When should I use Lazy<T>?

C#.NetLazy Evaluation

C# Problem Overview


I found this article about Lazy: Laziness in C# 4.0 – Lazy

What is the best practice to have best performance using Lazy objects? Can someone point me to a practical use in a real application? In other words, when should I use it?

C# Solutions


Solution 1 - C#

You typically use it when you want to instantiate something the first time its actually used. This delays the cost of creating it till if/when it's needed instead of always incurring the cost.

Usually this is preferable when the object may or may not be used and the cost of constructing it is non-trivial.

Solution 2 - C#

You should try to avoid using Singletons, but if you ever do need to, Lazy<T> makes implementing lazy, thread-safe singletons easy:

public sealed class Singleton
{
    // Because Singleton's constructor is private, we must explicitly
    // give the Lazy<Singleton> a delegate for creating the Singleton.
    static readonly Lazy<Singleton> instanceHolder =
        new Lazy<Singleton>(() => new Singleton());

    Singleton()
    {
        // Explicit private constructor to prevent default public constructor.
        ...
    }

    public static Singleton Instance => instanceHolder.Value;
}

Solution 3 - C#

A great real-world example of where lazy loading comes in handy is with ORM's (Object Relation Mappers) such as Entity Framework and NHibernate.

Say you have an entity Customer which has properties for Name, PhoneNumber, and Orders. Name and PhoneNumber are regular strings but Orders is a navigation property that returns a list of every order the customer ever made.

You often might want to go through all your customer's and get their name and phone number to call them. This is a very quick and simple task, but imagine if each time you created a customer it automatically went and did a complex join to return thousands of orders. The worst part is that you aren't even going to use the orders so it is a complete waste of resources!

This is the perfect place for lazy loading because if the Order property is lazy it will not go fetch all the customer's order unless you actually need them. You can enumerate the Customer objects getting only their Name and Phone Number while the Order property is patiently sleeping, ready for when you need it.

Solution 4 - C#

I have been considering using Lazy<T> properties to help improve the performance of my own code (and to learn a bit more about it). I came here looking for answers about when to use it but it seems that everywhere I go there are phrases like:

> Use lazy initialization to defer the creation of a large or > resource-intensive object, or the execution of a resource-intensive > task, particularly when such creation or execution might not occur > during the lifetime of the program.

from MSDN Lazy<T> Class

I am left a bit confused because I am not sure where to draw the line. For example, I consider linear interpolation as a fairly quick computation but if I don't need to do it then can lazy initialisation help me to avoid doing it and is it worth it?

In the end I decided to try my own test and I thought I would share the results here. Unfortunately I am not really an expert at doing these sort of tests and so I am happy to get comments that suggest improvements.

Description

For my case, I was particularly interested to see if Lazy Properties could help improve a part of my code that does a lot of interpolation (most of it being unused) and so I have created a test that compared 3 approaches.

I created a separate test class with 20 test properties (lets call them t-properties) for each approach.

  • GetInterp Class: Runs linear interpolation every time a t-property is got.
  • InitInterp Class: Initialises the t-properties by running the linear interpolation for each one in the constructor. The get just returns a double.
  • InitLazy Class: Sets up the t-properties as Lazy properties so that linear interpolation is run once when the property is first got. Subsequent gets should just return an already calculated double.

The test results are measured in ms and are the average of 50 instantiations or 20 property gets. Each test was then run 5 times.

Test 1 Results: Instantiation (average of 50 instantiations) > Class 1 2 3 4 5 Avg % > ------------------------------------------------------------------------ > GetInterp 0.005668 0.005722 0.006704 0.006652 0.005572 0.0060636 6.72 > InitInterp 0.08481 0.084908 0.099328 0.098626 0.083774 0.0902892 100.00 > InitLazy 0.058436 0.05891 0.068046 0.068108 0.060648 0.0628296 69.59

Test 2 Results: First Get (average of 20 property gets) > Class 1 2 3 4 5 Avg % > ------------------------------------------------------------------------ > GetInterp 0.263 0.268725 0.31373 0.263745 0.279675 0.277775 54.38 > InitInterp 0.16316 0.161845 0.18675 0.163535 0.173625 0.169783 33.24 > InitLazy 0.46932 0.55299 0.54726 0.47878 0.505635 0.510797 100.00

Test 3 Results: Second Get (average of 20 property gets) > Class 1 2 3 4 5 Avg % > ------------------------------------------------------------------------ > GetInterp 0.08184 0.129325 0.112035 0.097575 0.098695 0.103894 85.30 > InitInterp 0.102755 0.128865 0.111335 0.10137 0.106045 0.110074 90.37 > InitLazy 0.19603 0.105715 0.107975 0.10034 0.098935 0.121799 100.00

Observations

GetInterp is fastest to instantiate as expected because its not doing anything. InitLazy is faster to instantiate than InitInterp suggesting that the overhead in setting up lazy properties is faster than my linear interpolation calculation. However, I am a bit confused here because InitInterp should be doing 20 linear interpolations (to set up it's t-properties) but it is only taking 0.09 ms to instantiate (test 1), compared to GetInterp which takes 0.28 ms to do just one linear interpolation the first time (test 2), and 0.1 ms to do it the second time (test 3).

It takes InitLazy almost 2 times longer than GetInterp to get a property the first time, while InitInterp is the fastest, because it populated its properties during instantiation. (At least that is what it should have done but why was it's instantiation result so much quicker than a single linear interpolation? When exactly is it doing these interpolations?)

Unfortunately it looks like there is some automatic code optimisation going on in my tests. It should take GetInterp the same time to get a property the first time as it does the second time, but it is showing as more than 2x faster. It looks like this optimisation is also affecting the other classes as well since they are all taking about the same amount of time for test 3. However, such optimisations may also take place in my own production code which may also be an important consideration.

Conclusions

While some results are as expected, there are also some very interesting unexpected results probably due to code optimisations. Even for classes that look like they are doing a lot of work in the constructor, the instantiation results show that they may still be very quick to create, compared to getting a double property. While experts in this field may be able to comment and investigate more thoroughly, my personal feeling is that I need to do this test again but on my production code in order to examine what sort of optimisations may be taking place there too. However, I am expecting that InitInterp may be the way to go.

Solution 5 - C#

Just to expand upon the example posted by Matthew:

public sealed class Singleton
{
    // Because Singleton's constructor is private, we must explicitly
    // give the Lazy<Singleton> a delegate for creating the Singleton.
    private static readonly Lazy<Singleton> instanceHolder =
        new Lazy<Singleton>(() => new Singleton());

    private Singleton()
    {
        ...
    }

    public static Singleton Instance
    {
        get { return instanceHolder.Value; }
    }
}

Before the Lazy was part of the framework, we would have done it this way:

private static object lockingObject = new object();
public static LazySample InstanceCreation()
{
    if(lazilyInitObject == null)
    {
         lock (lockingObject)
         {
              if(lazilyInitObject == null)
              {
                   lazilyInitObject = new LazySample ();
              }
         }
    }
    return lazilyInitObject ;
}

Solution 6 - C#

From MSDN:

> Use an instance of Lazy to defer the creation of a large or resource-intensive object or the execution of a resource-intensive task, particularly when such creation or execution might not occur during the lifetime of the program.

In addition to James Michael Hare's answer, Lazy provides thread-safe initialization of your value. Take a look at LazyThreadSafetyMode enumeration MSDN entry describing various types of thread safety modes for this class.

Solution 7 - C#

You should look this example to understand Lazy Loading architecture

private readonly Lazy<List<int>> list = new Lazy<List<int>>(() =>
{
	List<int> configList = new List<int>(Thread.CurrentThread.ManagedThreadId);
	return configList;
});
public void Execute()
{
	list.Value.Add(0);
	if (list.IsValueCreated)
	{
		list.Value.Add(1);
		list.Value.Add(2);

		foreach (var item in list.Value)
		{
			Console.WriteLine(item);
		}
	}
	else
	{
		Console.WriteLine("Value not created");
	}
}

--> output --> 0 1 2

but if this code dont write "list.Value.Add(0);"

output --> Value not created

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiondanyolgiaxView Question on Stackoverflow
Solution 1 - C#James Michael HareView Answer on Stackoverflow
Solution 2 - C#MatthewView Answer on Stackoverflow
Solution 3 - C#DespertarView Answer on Stackoverflow
Solution 4 - C#BenView Answer on Stackoverflow
Solution 5 - C#Thulani ChivandikwaView Answer on Stackoverflow
Solution 6 - C#VaseaView Answer on Stackoverflow
Solution 7 - C#Tufy DuckView Answer on Stackoverflow