Why it’s sometimes good to be Lazy

I came across a situation recently in which we needed an object in the client. Due to the cost of creating this object, we didn’t want to create it when loading up the window as it might not be needed (if the user didn’t click the appropriate button), we didn’t want to store it on the window’s main object graph, but equally, we wanted to keep hold of it once it had been created.

This situation is not uncommon, where you have to create a class that is expensive (in database or bandwidth terms) to create.

The obvious solution to this was to have a private variable for the instance of Expensive, and a second private bool variable to indicate if the Expensive object had been created. We could check the bool before accessing the Expensive variable. Even better, we could create a property that wrapped this up. Imagine our class is wittily named Expensive…

private Expensive _expensive;
private bool _expensiveCreated;
 
private Expensive Expensive {
  get {
    if (!_expensiveCreated) {
      _expensive = new Expensive();
      _expensiveCreated = true;
    }
    return _expensive;
  }
}

Note that in many cases you can’t simply rely on checking if _expensive is not null, as null may well be a valid value (or lack thereof) for the object. Therefore, you need two variables.

This works, but has a few drawbacks. Firstly, it’s a lot of code for a simple requirement. Imagine you needed to do this for several types, you would end up with a lot of boilerplate code. Secondly, this method involves multiple variables for each expensive object you want. Finally, and most importantly, another developer coming along at some future date might not realise how it’s supposed to work, and assume that _expensive will always be available, bypassing the bool and causing a null reference exception. Even worse, when they discover the null reference, they might add extra code to create the object, ignoring the code you previously added to do just the same thing. This is not good.

A more elegant solution

Drum roll please… enter Lazy<T>. This neat little class (introduced in .NET 4.0) allows you to wrap all this up in one variable, and not have to worry about the details.

To illustrate, let’s define our Expensive class as follows…

public class Expensive {
  // For simplicity, this will be a simple class that writes a message to
  // the output window when it is created (so we can see when that happens)
  public Expensive() {
    Debug.WriteLine("Created new instance of Expensive, hash code is "
      + GetHashCode());
  }
  // Add a property, so we can reference something
  public int AnInteger { get; set; }
}

Instead of having the two private variables mentioned before, you just have one of type Lazy<Expensive>. When declaring it, you add the code that creates the instance as a constructor parameter. As a simple example, you could have something like this…

Lazy<Expensive> exLazy = new Lazy<Expensive>(() => new Expensive());

That’s about as simple as it gets, but there’s no reason why it couldn’t include more code that uses (say) a WCF service, database, EF model or whatever in there.

Now, the clever thing is that the class doesn’t get created until you actually want it. For example, see the following (rather over-the-top) code…

Debug.WriteLine("About to declare, but not use our lazy value");
Lazy<Expensive> exLazy = new Lazy<Expensive>(() => new Expensive());
Debug.WriteLine("Created the lazy value, but not used yet");
for (int i = 0; i < 5; i++) {
  Debug.WriteLine("  i: " + i);
  if (i > 1) {
    Debug.WriteLine("  Setting exLazy.Value.AnInteger to " + i);
    exLazy.Value.AnInteger = i;
  }
}
Debug.WriteLine("Ended loop, exLazy.Value.AnInteger is "
  + exLazy.Value.AnInteger);

This uses a liberal amount of writing to the Output window so we can see what’s happening. When you run it, you see the following…

About to declare, but not use our lazy value
Created the lazy value, but not used yet
  i: 0
  i: 1
  i: 2
  i: 3
  Setting exLazy.Value.AnInteger to 3
Created new instance of Expensive, hash code is 1707556
  i: 4
  Setting exLazy.Value.AnInteger to 4
  i: 5
  Setting exLazy.Value.AnInteger to 5
  i: 6
  Setting exLazy.Value.AnInteger to 6
  i: 7
  Setting exLazy.Value.AnInteger to 7
  i: 8
  Setting exLazy.Value.AnInteger to 8
  i: 9
  Setting exLazy.Value.AnInteger to 9
Ended loop, exLazy.Value.AnInteger is 9

As you can see, the Expensive class isn’t actually created until you want it, and from then on, it exists without needing to check it, or create it again. This means that your code can just refer to exLazy.Value all the way through, and rely on the fact that if it doesn’t exists, it will be created for you.

The Lazy<T> class also has also a bool property IsValueCreated, which (oddly enough) allows you to check if the value has been created. Not sure quite how useful that is, but it’s there if you need it.

Not the sort of thing you need to use every day, but when you do, it provides a more elegant and low-risk approach than the first method.

Be First to Comment

Leave a Reply

Your email address will not be published.

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