Share via


Lazy Computation in C#

by Tomas Petricek
October 2007

Most of the programming languages used in practice (including for example C#, VB.NET, C++, Python or Java) employ so called eager evaluation, which means that the program evaluates all expression and statements in the order in which they are written, so all the preceding statements and expressions are evaluated before executing the next piece of code. This, for example, means that all arguments to a method call are evaluated before calling the method. Sometimes it may be useful to delay an execution of some code until the result is actually needed, either because the result may not be needed at all (but we can’t tell that before executing some computation) or because we don’t want to block the program for a long time by executing all computations in advance and instead we want to execute the computations later, when we will actually need the result.

In this article we will look how these lazy computations can be written in C# (using some of the new language features from version 3.0). We will first implement a Lazy class to represent this kind of computation, then look at a few simple examples to demonstrate how the class can be used, and finally we will examine one slightly more complicated, but practically useful application.

The Lazy<T> Class

We will start by writing a generic class Lazy<T>, which represents the delayed computation. This class can be described as a class that will execute a chunk of code once someone asks for a result and it will cache the result, so the chunk of code is executed at most once. How can we write such class in C#? It is easy: we can use a Func delegate to represent the “chunk of code” that will be executed, and we can use generics to write a class that can represent computations returning any .NET type:

using System.Linq;public class Lazy<T> {  private Func<T> func;  private T result;  private bool hasValue;  public Lazy(Func<T> func) {    this.func = func;    this.hasValue = false;  }  public T Value {    get {      if (!this.hasValue) {         this.result = this.func();         this.hasValue = true;       }      return this.result;    }  }}

The class has three fields: the func field is a delegate that will be executed when someone will access the value, the hasValue field is a logical value saying whether we already called the delegate, and finally, the result field stores the result after calling the delegate. All the important logic of the class is in the Value property, which returns a value calculated by the delegate. The getter of the property first tests if we already have the result, and if not, it calls the delegate and stores the result. Otherwise we can just return the result that was calculated earlier.

Let’s now look at how can we use this class. Its constructor expects a value of the type Func<T> (from the System.Linq namespace), which is new in .NET 3.5 and represents a delegate that doesn’t have any arguments and returns a value of type T. The advantage of using this type is that we can use C# 3.0 anonymous functions to write code that will be executed in a very compact way directly when creating an instance of the Lazy<T> value. In the following example we create a lazy value that will return a numeric value once it is executed, but it will also print a string to the console window when it is executed, so we can trace when the code runs:

Lazy<int> lazy = new Lazy<int>(() => {    Console.WriteLine("calculating...");    return 42;  });Console.WriteLine("starting..."); Console.WriteLine("result = {0}", lazy.Value); Console.WriteLine("result (again) = {0}", lazy.Value); 

In this code we first created a variable called lazywhich represents our lazy value, then printed a string to the console window, and finally we used the Value property of the lazy value to read the result of the computation (even twice!). As you may have expected, the output of this program is following:

starting...calculating...result = 42result (again) = 42

What exactly happened? When we created a lazy value, the program just created a delegate from the anonymous function, but it didn’t execute it when creating the value, so it didn’t print anything to the screen. Later the first WriteLine executed and printed the "starting..." string. Next, when calling the second WriteLine, we accessed the Value property of our lazy value, so the anonymous function was executed, printed the "calculating..." string and returned the result. The result was given as an argument to the WriteLine function and it printed the string "result = 42". Finally, we accessed the Value property again, but since the value was already calculated, the lazy value just returned the cached result and the last WriteLine call was performed printing the string "result (again) = 42".

Leveraging from the C# Type Inference

Before moving to more interesting and far more useful examples, we will do one more improvement to the way we write lazy values. The syntax used for creating lazy value in the previous example is somewhat too verbose, because we had to write Lazy<int> twice. Luckily, we can easily simplify it by using C# type inference. In C# it is possible to omit the type arguments when calling a generic method, so we will write a simple static helper class with a static method for creating a lazy value. (Helper classes like this exist in other places of the .NET Framework; for example, System.Nullable has a similar purpose.)

public static class Lazy {  public static Lazy<T> New<T>(Func<T> func) {    return new Lazy<T>(func);  }}

Using this class, we can create a lazy value just by calling Lazy.New instead of writing new Lazy<int>. To get even more compact syntax, we can also combine this syntax with the new C# 3.0 var keyword, which tells the compiler to infer the type of a variable automatically depending on the expression used to initialize the variable. Additionally, this little helper class also enables using C# 3.0 anonymous types. These, of course, can be used only locally (inside a method), but may often be useful, as demonstrated in the following example, where we use anonymous type to create a lazy value representing both the sum and product of two numbers:

int a = 22, b = 20;var lazy = Lazy.New(() => {    Console.WriteLine("calculating...");    return new { Mul = a*b, Sum = a+b };  });Console.WriteLine("Mul = {0}, Sum = {1}",   lazy.Value.Mul, lazy.Value.Sum); 

Lazy Value as an Argument of a Method

In the introduction I mentioned that one of the aspects of eager evaluation(used in most programming languages, including C#) is that arguments of a method are evaluated before calling the method, which may not be the best thing to do if the calculation can take a long time to complete and a method may not actually need the value. On the other side, in lazy evaluation, the arguments are never evaluated unless the value is actually required in the method body ,and indeed this behavior can be nicely simulated using our lazy values. The following method takes two lazy values, but in fact uses only one of them:

static Random rnd = new Random();static void UseRandomArgument(Lazy<int> a0, Lazy<int> a1) {  int res;  if (rnd.Next(2) == 0)     res = a0.Value;   else     res = a1.Value;  Console.WriteLine("result = {0}", res);}

To call this method, we create two lazy values (using the Lazy.New method), and to demonstrate how the code behaves, we also add a Console.WriteLine call to the anonymous function used for calculating the value.

var calc1 = Lazy.New(() => {    Console.WriteLine("Calculating #1");    return 42;  });var calc2 = Lazy.New(() => {    Console.WriteLine("Calculating #2");    return 44;  });UseRandomArgument(calc1, calc2);UseRandomArgument(calc1, calc2);

Since the UseRandomArgument function randomly uses only one of the arguments, we can get a different result every time we execute the application. The purpose of this example is to demonstrate that the code to calculate the argument may not be executed (if the argument is never used), which may happen, for example, when the function chooses to read a value of the first argument ( calc1) in both calls. In such a case, the second value ( calc2) is never used and we get the following output:

Calculating #1Result = 42Result = 42

Note that the line that would be printed when calculating the second argument ( "Calculating #2") isn’t present in the output. Of course, if the function uses a different argument in each call, we can get output like following, in which case both of the lazy values were forced to execute:

Calculating #1Result = 42Calculating #2Result = 44

Example: Font List with Preview

As a last thing in this article we will use the Lazy<T> class to write a more interesting application. As you can see in Figure 1, the application contains a drop-down list with font families, and the font preview is shown when the font is selected. How can we use our lazy values in this application? We don’t want to draw previews of all the font families when populating the list, but we would like to draw the preview bitmap for every font only once to save some CPU time—and this is exactly what the lazy values are good for!

screenshot: Font List with Preview

Figure 1: The form for the Font Application contains a drop-down list of font names and an area where the selected font can be previewed.

We will need a data type for storing information about the font, so we define a class with two properties: one is the font name, which is an ordinary string, and the other is a lazy value storing a bitmap (the preview of the font). In addition, we can use C# 3.0 automatic properties to save some time when implementing the class. (When using automatic properties, the C# compiler generates a trivial getter and setter for us.)

private class FontInfo {  public Lazy<Bitmap> Preview { get; set; }  public string Name { get; set; }}

Before looking at the interesting part of the code, we will also need a utility method to draw the preview of the font. The DrawFontPreview method from the following code sample does exactly that: it uses System.Drawing classes to draw a white rectangle with some text using the specified font family.

private void DrawFontPreview(FontFamily f, Bitmap bmp) {  Rectangle rc = new Rectangle(0, 0, 300, 200);  StringFormat sf = new StringFormat();  sf.Alignment = StringAlignment.Center;  sf.LineAlignment = StringAlignment.Center;  string lipsum = "Lorem ipsum dolor sit amet, consectetuer " +    "adipiscing elit. Etiam ut mi blandit turpis euismod malesuada. " +    "Mauris congue pede vitae lectus. Ut faucibus dignissim diam. ";  using (Font fnt = new Font(f, 15, FontStyle.Regular))  using (Graphics gr = Graphics.FromImage(bmp)) {    gr.FillRectangle(Brushes.White, rc);    gr.DrawString(lipsum, fnt, Brushes.Black, rc, sf);  }}

Let’s look at the code that populates the list. First we use the FontFamily.Families property to get an array with information about all the installed fonts. Now, we want to create a list containing a FontInfo instance for every font family in the array. We could indeed allocate an array and use a for loop to do this, but it is much easier to take advantage of another new .NET 3.5 feature and use the Select query operator. Select is an extension method for all IEnumerable types, so we can use it for an array as well. It takes a delegate as an argument, calls this delegate for every element in the sequence, and returns an IEnumerablecontaining results returned by the delegate. In our case we give it an anonymous function with a body that builds a lazy value for drawing the preview and returns a FontInfo value for every font family. After creating this IEnumerable value, we use it to populate the items in the drop-down list using data-binding:

private void FontForm_Load(object sender, EventArgs e) {  var fontInfo = FontFamily.Families.Select(f => {      // Create a lazy value for drawing the preview      var preview = Lazy.New(() => {          Bitmap bmp = new Bitmap(300, 200);          DrawFontPreview(f, bmp);           return bmp;        });      // Return a font info with the family name and the preview      return new FontInfo { Name = f.Name, Preview = preview };    });  // Use data-binding to populate the drop down list  fontCombo.DataSource = fontInfo.ToList();  fontCombo.DisplayMember = "Name";}

The last missing piece of the application is an event handler that displays the preview of the selected font when the user selects an item in the drop-down list. To do this we simply read the SelectedItemproperty of the drop-down list, cast it to the FontInfotype that we used to store information about the font, and we get the preview bitmap from the Preview lazy value using the Value property, which forces the evaluation of the value.

private void fontCombo_SelectedIndexChanged(object sender, EventArgs e) {  FontInfo fnt = (FontInfo)fontCombo.SelectedItem;  fontPreview.Image = fnt.Preview.Value;}

Conclusion

In this article we looked at representing lazy values in C# using the Lazy<T> class, which can be a very useful pattern in situations where you want to delay a computation of some expression until the result is actually needed, but you want to keep the code simple and readable. We also examined an example that demonstrates using the lazy pattern to solve a more real-world problem. Finally, we used some of the new C# 3.0 language features (including type inference, anonymous functions, query operators and anonymous types) to make the code more compact and easier to read.