Introduction
.NET Framework provides us with a new class called Lazy<T>
which is used to initialize the object in lazy pace. It includes the ability to initialize the value types and to use null
values. Using this class, we could implement complex navigation related applications very effectively with less memory use. For instance, consider the situation like I have a property which holds array of user controls (approx 50 User controls) in Silverlight application. In this instance, I need to display five user controls in main page, but need to initiate all these fifty user controls to get the actual references while application loads since I need to bind some elements between user controls. At the same time, rest of the user controls will be displayed when user navigates explicitly.
Prerequisites
- .NET Framework 4.0
- Windows XP, 2003, Vista, Windows7, VS2010
Typical .NET Object Initialization
If we implement such an application using typical .NET property declaration/initialization without using the Lazy
class, all the user controls will be initialized when we use new
keyword while adding items in my array property. Below is the typical .NET initialization.
private UserControl[] loadMyUserControl;
public UserControl[] LoadMyUserControl
{
get
{
return loadMyUserControl;
}
set
{
loadMyUserControl = value;
}
}
public MainPage()
{
InitializeComponent();
var userControls = new UserControl[]
{
new UserControl1(),
new UserControl2(),
new UserControl3()
};
}
In this approach, my application consumes unnecessary memory (nearly 45 user control memory) when user opens my application and closes without navigating into other pages.
Lazy Initialization
But Lazy initialization occurs the first time the Lazy<T>.Value
property is accessed or the Lazy<T>.ToString
method is called. For my scenario, five user controls instance and memory is only created while loading my application. Rest of the user controls will be created when user navigates to the corresponding page through navigation link from my main page. Below is the code snippet for lazy load.
private Lazy[] loadMyUserControl;
public Lazy[] LoadMyUserControl
{
get
{
return loadMyUserControl;
}
set
{
loadMyUserControl = value;
}
}
public MainPage()
{
InitializeComponent();
LoadMyUserControl = new Lazy[]
{
new Lazy(() => {return new UserControl1();
}),
new Lazy(() => {return new UserControl2();
}),
new Lazy(() => {return new UserControl3();
})
};
}
Now I am going to load my user controls based on navigation at runtime as below mentioned:
private void Button_Click_1(object sender, RoutedEventArgs e)
{
if (!TopPanel.Children.Contains(LoadMyUserControl[5].Value))
TopPanel.Children.Add(LoadMyUserControl[5].Value);
}
Note: TopPanel
is the stack panel which is in the main page of the application. See the demo sample for more idea.
Run the demo app and click “Status” button. Check the status of user controls. Still all the user controls are not loaded as shown in the below mentioned snap.
Click “Load UserControl1” button and check the status. Now you could see, first user control is loaded in view and status has been changed as True
. What a great feature in framework 4.0. :)
You can refer to this in MSDN documentation for more ideas about the Lazy
class.
Points of Interest
Actually, I noticed this feature when I started to read about MEF :). It seems MEF uses this feature predominantly to import/export contracts. But I am not sure about it. Because I am not an MEF author. :)
History
- 26th August, 2010: Initial post