One of the pretty cool new nuggets inside the .Net 4.0 framework is System.Lazy and System.Lazy<T>. What System.Lazy brings to the table is a way to create objects which may need to perform intensive operations and defer the execution of the operation until it is 100% absolutely needed.
Lets take a look at how to use the System.Lazy type.
To better convey how to use this type we should first create some context. In our example (trivial i know) we will have an orders factory which creates orders. Take a look at the code below.
public class OrdersFactory
{
public IList FetchOrders()
{
Console.WriteLine( "About to fetch orders" );
return new List<Order>:
{
new Order {OrderId = 1, InvoiceNumber = 1, OrderAmount = 19.95D, ItemCount = 2},
new Order {OrderId = 2, InvoiceNumber = 2, OrderAmount = 29.95D, ItemCount = 3},
new Order {OrderId = 3, InvoiceNumber = 3, OrderAmount = 33.25D, ItemCount = 4},
new Order {OrderId = 4, InvoiceNumber = 4, OrderAmount = 19.95D, ItemCount = 1},
new Order {OrderId = 5, InvoiceNumber = 5, OrderAmount = 204.17D, ItemCount = 10},
new Order {OrderId = 6, InvoiceNumber = 6, OrderAmount = 32.54D, ItemCount = 4},
};
}
public Order FetchOrder()
{
Console.WriteLine( "About to fetch single order" );
return new Order {OrderId = 1, InvoiceNumber = 1, OrderAmount = 19.95D, ItemCount = 2};
}
}
public class Order
{
public Int32 OrderId { get; set; }
public Int32 InvoiceNumber { get; set; }
public double OrderAmount { get; set; }
public Int32 ItemCount { get; set; }
}
Pay attention to the Console.WriteLine in each factory method, these lines will provide us an indication of when the execution of these methods takes place.
Now that we have context, lets look at the example code for System.Lazy
In the code below we are going to call into the order factory and NOT use the values it returns right away.
class Program
{
static void Main( string[] args )
{
var ordersFactory = new OrdersFactory();
Console.WriteLine("Fetching order info --- non lazy");
var ordersAsNonLazy = ordersFactory.FetchOrders();
var orderAsNonLazy = ordersFactory.FetchOrder();
Console.ReadLine();
}
}
If we run this console application you will receive the following information:
You will notice that the second I call into the 2 methods they are executed, which is what is expected. Now lets use the .Lazy namespace and see what changes
class Program
{
static void Main( string[] args )
{
var ordersFactory = new OrdersFactory();
Console.WriteLine("Fetching order info --- non lazy");
var ordersAsNonLazy = ordersFactory.FetchOrders();
var orderAsNonLazy = ordersFactory.FetchOrder();
Console.WriteLine( "-----" );
Console.WriteLine( "-----" );
Console.WriteLine( "Fetching order info --- lazy" );
var ordersAsLazy = new Lazy<IList<Order>>( () => { return ordersFactory.FetchOrders(); } );
var orderAsLazy = new Lazy<Order>( () => { return ordersFactory.FetchOrder(); } );
Console.WriteLine( "Fetching order info --- lazy -- created lazy objects...." );
Console.WriteLine( "Has Data been fetched for List? - {0}", ordersAsLazy.IsValueCreated );
Console.WriteLine( "Has Data been fetched for Order? - {0}", orderAsLazy.IsValueCreated );
Console.WriteLine( "Fetching order info --- lazy -- using lazy objects...." );
var orders = ordersAsLazy.Value;
var order = orderAsLazy.Value;
Console.WriteLine( "Has Data been fetched for List? - {0}", ordersAsLazy.IsValueCreated );
Console.WriteLine( "Has Data been fetched for Order? - {0}", orderAsLazy.IsValueCreated );
Console.ReadLine();
}
}
If we rerun this console application you will receive the following information:
Here you will notice that i have created my points to the methods, but they have not been executed. I know this by taking a look at the .IsValueCreated property on the Lazy type. Since this has returned False I know my pointers have not been executed. However, the second we call .Value you will see the messages appear which tell us the pointers have been executed.
Finally, if i recheck the .IsValueCreated property this time it returns True which tells me we have indeed executed our pointers.
As you can see using Lazy is easy and can be a very powerful tool in your tool chest. But like everything else, this feature of the framework is NOT meant for ever scenario, use it where it makes sense.
Till next time,
Posted
05-19-2010 5:51 AM
by
Derik Whittaker