Laziness in C# 4.0 – Lazy<T>

Posted: October 4, 2009 in .NET, C#
Tags: , ,

Lazy Instantiation” defers creation of an object till the time it is actually accessed.The process of object creation is always expensive as it involves allocation of memory on the heap.So Lazy Instantiation optimizes resources by using them when it is actually required.Till C# 3.0 we needed to some custom coding to implement “Lazy Instantiation” pattern.Now C# 4.0 introduces the Lazy<T> class as part of BCL for this purpose.In this post we will take a detailed look into the behavior and functioning of this class.

Let us refer to the following lines of code:

class Program
{
    static void Main(string[] args)
    {
        Lazy<Foo> f = new Lazy<Foo>( );
        Console.WriteLine("Foo is defined");
        if (!f.IsValueCreated) Console.WriteLine("Foo is not initialized yet..");
        Console.WriteLine("Foo::ID=" + (f.Value as Foo).ID);
        if (f.IsValueCreated) Console.WriteLine("Foo is initialized now..");
        Console.Read(); 

    }
} 

public class Foo
{
    public int ID { get; set; } 

    public Foo()
    {
        Console.WriteLine("Foo:: Constructor is called");
        ID = 1;
    }
}

This program will print the following:

Foo is defined
Foo is not initialized yet..
Foo:: Constructor is called
Foo::ID=1
Foo is initialized now..

Here the object of Foo is created only when f.Value is accessed.The property Value returns the instance of the lazily initialized object.The boolean property IsValueCreated indicates whether the lazy object is initialized or not.We can pass a delegate which returns object of type Foo in the constructor as shown below:

Lazy<Foo> f = new Lazy<Foo>
                (
                    ()=> 
                    { 
                        Foo fobj = new Foo() { ID = 99 }; 
                        return fobj; 
                    }
                );

In this case the program will print

Foo is defined
Foo is not initialized yet..
Foo:: Constructor is called
Foo::ID=99
Foo is initialized now..

The uses of the Lazy<T> class discussed above are all non threadsafe i.e the object will be initialized once even if multiple threads are racing for it.We can make it threadsafe by using the following constructors:

  • public Lazy(LazyExecutionMode mode)
  • public Lazy(Func<T> valueFactory,LazyExecutionMode mode)

Here we have to pass the System.Threading.LazyExecutionMode enumeration.This enumeration supports the following values:

  • NotThreadSafe
  • AllowMultipleThreadSafeExecution – This allows the initializer to be executed multiple times and one value is published for all threads to access.
  • EnsureSingleThreadSafeExecution – This allows the initializer to be executed once even when multiple threads are trying to access the value and finally the value is published to all the threads.

Let us explore this with some examples.I have written the method Run which accepts a lazy object as shown below:

static void Run(object obj)
 {
     Lazy<Foo> flazy = obj as Lazy<Foo>;
     Foo f = flazy.Value as Foo;
     f.ID++;
     Console.WriteLine("Foo::ID=" + f.ID); 

 }

In the main program I have instantiated the Lazy object with LazyExecutionMode.EnsureSingleThreadSafeExecution as shown below:

static void Main(string[] args)
{
    Lazy<Foo> f = new Lazy<Foo>
        (
            ()=> 
            { 
                Foo fobj = new Foo() { ID = 99 }; 
                return fobj; 
            },LazyExecutionMode.EnsureSingleThreadSafeExecution
        );
    Console.WriteLine("Foo is defined");
    ThreadPool.QueueUserWorkItem(new WaitCallback(Run),f);
    ThreadPool.QueueUserWorkItem(new WaitCallback(Run), f);

    Console.Read(); 

}

The program output is:

Foo is defined
Foo:: Constructor is called
Foo::ID=100
Foo::ID=101

This clearly shows that constructor is called once and then the value is published to the other threads.Now I am making a small change in the Run method as shown below and changing the mode to LazyExecutionMode.AllowMultipleThreadSafeExecution

static void Run(object obj)
 {
     Lazy<Foo> flazy = obj as Lazy<Foo>;
     Foo f = flazy.Value as Foo;
     f.ID++;
     Thread.Sleep(100);
     Console.WriteLine("Foo::ID=" + f.ID); 

 }

The program output is:

Foo is defined
Foo:: Constructor is called
Foo:: Constructor is called

Foo::ID=101
Foo::ID=101

So here the constructor is called twice and then the final value is published to all the threads.

Comments
  1. […] Laziness in C# 4.0 – Lazy<T> « Sankarsan’s Journal sankarsan.wordpress.com/2009/10/04/laziness-in-c-4-0-lazyt – view page – cached “Lazy Instantiation” defers creation of an object till the time it is actually accessed.The process of object creation is always expensive as it involves allocation of memory on the heap.So Lazy… (Read more)“Lazy Instantiation” defers creation of an object till the time it is actually accessed.The process of object creation is always expensive as it involves allocation of memory on the heap.So Lazy Instantiation optimizes resources by using them when it is actually required.Till C# 3.0 we needed to some custom coding to implement “Lazy Instantiation” pattern.Now C# 4.0 introduces the Lazy class as part of BCL for this purpose.In this post we will take a detailed look into the behavior and functioning of this class. (Read less) — From the page […]

  2. Laziness in C# 4.0 – Lazy « Sankarsan’s Journal…

    DotNetBurner – burning hot .net content…

  3. Laziness in C# 4.0 – Lazy « Sankarsan’s Journal…

    Thank you for submitting this cool story – Trackback from PimpThisBlog.com…

  4. Laziness in C# 4.0 – Lazy « Sankarsan’s Journal…

    Thank you for submitting this cool story – Trackback from DotNetShoutout…

  5. dotnetchris says:

    This is great news, lazy instantiation was always a needless hassle. I’m glad the BCL will finally include this.

    Now if only they would make it so I can use Nullable

  6. dotnetchris says:

    That should say Nullabe&ltstring&gt

  7. Suresh says:

    When the object gets created, does it use Object initializer? I prefer not to use that because theoritically in memory 2 objects get created when we object initializer. I would rather use properly defined constructor…

  8. […] Read more: Sankarsan’s Journal […]

  9. kokhonomegh says:

    the ctor “public Lazy(Func valueFactory,LazyExecutionMode mode)” seems to be replaced by “public Lazy(Func valueFactory,bool isThreadSafe)” in Beta 2

  10. I’m glad to see the laziness principle being implemented in some shape of form, although it feels a bit hacky. You’d technically want the compiler to it automatically, not have to use a specific class. But I suppose it’s a step in the right direction.

  11. According to the docs (http://msdn.microsoft.com/en-us/library/dd642177(VS.100).aspx), the Value property is defined as of type T. But in your code example you cast to T. Any reason why?

  12. Ecko says:

    nice article… thanks

  13. […] erst durchführt wenn die Daten benötigt werden. Weitere Informationen auf der MSDN Seite oder auf diesem […]

  14. IG says:

    Thank you.

  15. Martin Kunc says:

    Cool content, I like the new Lazy concept in fx 4

  16. pavan Kumar says:

    Really Nice article………Thanks a lot………:)

  17. Wishwekar says:

    As on date, there is no “LazyExecutionMode” enum defined in .Net4.0 or 4.5.

  18. John says:

    “The process of object creation is always expensive as it involves allocation of memory on the heap”.
    Mmm, maybe in non-managed environments this statement holds true, but in a managed enfironment this is usaally NOT the case. Allocation of memory in an managed environment usually involves nothing more that moving a pointer the required number of bytes foreward. Garbage collection on the other hand, can be more expensive. Check out the document written by Jeffrey righter on the subject of garbage collection, to see what I mean.

  19. […] I found this article about Lazy: Laziness in C# 4.0 – Lazy […]

  20. tafs7 says:

    System.Threading.LazyExecutionMode was replaced by System.Threading.LazyThreadSafetyMode for the final and current API

  21. […] I found this article about Lazy: Laziness in C# 4.0 – Lazy […]

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.