Lazy

I love it when I find a new .NET class that I have never used before. That just happened to me, I cam across a little class called Lazy<T>.

The idea behind Lazy<T> is that it is a simple wrapper for an object that may be expensive to create, maybe one that hits the database or something like that. And you do not want to create this object until you need to, that is what Lazy<T> is all about.

It is very simple to use, all you need to do is specify the type of T, and then you can examine the wrapped value to see if has been created yet using the Lazy<T>.IsValueCreated property. Simliarly if you want to get the actual T instance out, you just need to use the Value property.

Here is small example of setting it up and using it

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace Laziness
{
    class Program
    {
        static void Main(string[] args)
        {
            //Construction normally
            Lazy<SomeExpensiveClass> someExpensiveClass = 
                new Lazy<SomeExpensiveClass>();

            Console.WriteLine(String.Format(
                "someExpensiveClass has value yet {0}",
                someExpensiveClass.IsValueCreated));
            Console.WriteLine(String.Format(
                "someExpensiveClass.SomeProperty value {0}",
                ((SomeExpensiveClass)someExpensiveClass.Value).
            SomeProperty.ToString()));
            Console.WriteLine(String.Format(
                "someExpensiveClass has value {0}",
                someExpensiveClass.IsValueCreated));

        }


    }



    public class SomeExpensiveClass
    {
        public int SomeProperty { get; set; }

        public SomeExpensiveClass()
        {
            Console.WriteLine("SomeExpensiveClass constructed");
        }
    }
}

Which would show the following

lazy1[3]

You can also use a Func<T> to control how the object is created, here is an example of that

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace Laziness
{
    class Program
    {
        static void Main(string[] args)
        {

            //Construction up using a Func for more specific construction
            Lazy<SomeExpensiveClass> someExpensiveClass2 = 
        new Lazy<SomeExpensiveClass>
                (
                    ()=>
                    {
                        SomeExpensiveClass fobj = new SomeExpensiveClass() 
                        { 
                            SomeProperty = 100 
                        };
                        return fobj;
                    }
                );
            Console.WriteLine(String.Format(
                "someExpensiveClass2 has value yet {0}", 
                someExpensiveClass.IsValueCreated));
            Console.WriteLine(String.Format(
                "someExpensiveClass2s.SomeProperty value {0}",
                ((SomeExpensiveClass)someExpensiveClass2.Value).SomeProperty.ToString()));

            Console.WriteLine(String.Format(
                "someExpensiveClass2 has value yet {0}", 
                someExpensiveClass.IsValueCreated));


            Console.ReadLine();

        }

    }



    public class SomeExpensiveClass
    {
        public int SomeProperty { get; set; }

        public SomeExpensiveClass()
        {
            Console.WriteLine("SomeExpensiveClass constructed");
        }
    }
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Which when run looks like this:

lazy2[1]

And you can also ensure thread safety, have a look at this snippet

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace Laziness
{
    class Program
    {
        static void Main(string[] args)
        {

            //Construction up using a Func for more specific construction
            Lazy<SomeExpensiveClass> someExpensiveClass3 = 
                new Lazy<SomeExpensiveClass>
                (
                    () =>
                    {
                        SomeExpensiveClass fobj = new SomeExpensiveClass() 
                            { 
                                SomeProperty = 100 
                            };
                        return fobj;
                    },
                    true //is threadsafe
                );
            Console.WriteLine("Starting threaded test");
            //The Lazy object ctor is called twice and published to 
            //all threads, and as it was thread safe they all get same value
            ThreadPool.QueueUserWorkItem(new WaitCallback(DoThread), 
                someExpensiveClass3);
            ThreadPool.QueueUserWorkItem(new WaitCallback(DoThread), 
                someExpensiveClass3);

            Console.ReadLine();

        }



        static void DoThread(object obj)
        {
            Lazy<SomeExpensiveClass> lazy = 
        (Lazy<SomeExpensiveClass>)obj;
            SomeExpensiveClass someExpensiveClass3 = 
        (SomeExpensiveClass)lazy.Value;
            someExpensiveClass3.SomeProperty++;
            Thread.Sleep(10);
            Console.WriteLine(String.Format(
                "someExpensiveClass3.SomeProperty value {0}",
                someExpensiveClass3.SomeProperty.ToString()));
        }


    }



    public class SomeExpensiveClass
    {
        public int SomeProperty { get; set; }

        public SomeExpensiveClass()
        {
            Console.WriteLine("SomeExpensiveClass constructed");
        }
    }
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Which when run looks like this:

lazy3[1]

As always here is a small demo project : Small demo project

 

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Advertisements

6 thoughts on “Lazy

  1. bitbonk says:

    You should have mentioned that this is .NET 4.0 only.

  2. Although Lazy is available (and has been for some time) as part of the “Rx” and “MEF” DevLabs / Codeplex releases for .NET 3.5 and Silverlight 3. Lazy in conjunction with MEF is particularly lovely.

  3. Guy says:

    uber-cool indeed.

    i just love .net4 and looking forward to the day we’ll migrate…

    continue doing the great things you do!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: