Today, we’re covering how to use a particular feature of .NET 4 to implement lazy loading within a class.  What is lazy loading (or more technically, lazy initialization)?  MSDN defines it as this:

Lazy initialization of an object means that its creation is deferred until it is first used

For those of you who utilize Entity Framework, you are already familiar with this concept.  LINQ queries and foreign key relationships do not actually access the database to retrieve the information until an operation within the application utilizes the information.  For example, consider a Customer object with Name and Phone Number properties as well as a list of Orders.  In the EF world, the Name and Phone number would be populated from the database as the object is created.  However, no query is ran for the orders until a component of the code requests the Orders parameter.  At that time the SQL is generated and executed, returning the queryable Orders object.  The reasoning behind it is straightforward: there could be millions of Orders in the database therefore loading them all up front is a very resource intensive operation.  Deferring that operation until the moment it is needed gives the advantage of never querying the orders at all if that information is not required for the function being executed.

As of .NET 4, C# provides the typed Lazy<t> class that gives us the ability to easily implement lazy loading for ourselves when it is needed.  Consider the following complexObject class that contains an int, string, and an enumeration of a complex objects (Tuple<double, string> in this case):

class baseObject
{
    public static int setSize = 500000;
    public string simpleString { get; set; }
    public int simpleInt { get; set; }

    protected IEnumerable<Tuple<double, string>> _complexList;

    public virtual IEnumerable<Tuple<double, string>> complexList
    {
        get
        {
            return (_complexList);
        }
    }

    protected IEnumerable<Tuple<double, string>> fakeDBCall()
    {
        // faux database call to consume time
        var rand = new Random(((int)DateTime.Now.Ticks % int.MaxValue));
        var result = new double[setSize];
        for (int x = 0; x < setSize; x++)
        {
            result[x] = rand.NextDouble() * double.MaxValue;
        }
        return ((result.Select(x => new Tuple<double, string>(x, x.ToString()))).ToList());
    }
}

class complexObject : baseObject
{
    public complexObject()
    {
        simpleString = "Some string";
        simpleInt = 42;
        _complexList = fakeDBCall();
    }
}

At the time of object construction, fakeDBCall() is executed, running through a time consuming loop to create random data and simulate a database call. In the scenario where many complexObjects are being utilized but only some of them require access to their respective complexLists, executing this constructor for every instance would be inefficient. It is possible to move fakeDBCall() into a get accessor for the object, however this would be executed on every call to the property. What is needed is for this example is a mechanism to generate the data from fakeDBCall() the first time the property is accessed, and return the same object on subsequent accesses. Lazy can help. Here is an example implementation of a complexLazyObject:

class complexLazyObject : baseObject
{
    private Lazy<IEnumerable<Tuple<double, string>>> _lazyList;

    public override IEnumerable<Tuple<double, string>> complexList
    {
        get
        {
            return (_lazyList.Value);
        }
    }
    public complexLazyObject()
    {
        simpleString = "Some string";
        simpleInt = 16309;
        _lazyList = new Lazy<IEnumerable<Tuple<double, string>>>(fakeDBCall);
    }
}

The changes begin by defining a new object (_lazyList) that is defined with the type Lazy>>. In the constructor, _lazyList is initialized with the function that mimics our database call. The complexList property is then overridden to return the Value property of our new _lazyList. As _lazyList itself is the Lazy object, .Value contains the results of the constructor passed into it (fakeDBCall). The end result is that execution of fakeDBCall() is deferred until code actually accesses the complexList property of our complexLazyObject, and we have achieved our lazy loading. Subsequent use of complexList will return the same object that was created the first time complexList was accessed; fakeDBCall is not executed upon every access.

I constructed a simple demo app around these classes that shows the lazy loading and deferred execution. Running on my laptop, the timing results were:

Bench start
Bench finish, results
Normal Constructor :            456.735 ms
Lazy Constructor :              0.501 ms
Normal First Access :           0.000 ms
Lazy First Access :             427.282 ms
Normal Second Access :          0.000 ms
Lazy Second Access :            0.000 ms

As you can see, the fake DB call was successfully deferred until the property was accessed.

The demo app is available at https://www.github.com/mybridgepoint/diylazy.