The .NET 4.0 framework is shipped with many new features, considering all aspects of development. To increase the performance and reduce memory consumption a new feature was introduced known as "Lazy Initialization". With earlier versions of .NET it could be implemented using some custom class but now you don't need to worry about it, just focus on the business logic, the framework will take care of your objects. Lazy initialization or lazy loading is the idea that the object will not be constructed, created, initialized, or loaded until it is absolutely needed. In this post, we'll see the different ways to use the Lazy feature.
Lazy initialization can be seen in designing the singleton pattern where we can have a static readonly property in a nested class that initializes the singleton object in a Lazy way.
Lazy<T> wrapper introduced to provide the support for Lazy initialization with its several overloads. The Lazy<T> may or may not ensures thread-safe initialization as it considers the performance and if required removes the thread-safe environment with locking & synchronization that can result in little effect on performance. But if you want to ensure that initialization should be thread-safe then you can use its overloads.
There are six overloads of Lazy<T>:
Initializes a new instance of the Lazy<T> class. When lazy initialization occurs, the default constructor of the target type is used.
e.g.
When lazy initialization occurs, the default constructor of the target type and the specified initialization mode is used. i.e. considering the isThreadSafe.
- /// <summary>
- /// Thread safe Singleton generic for earlier versions
- /// </summary>
- public class Singleton <T> where T:new()
- {
- private Singleton() {}
- public static T Instance
- {
- get { return SingletonCreator._instance; }
- }
- class SingletonCreator
- {
- static SingletonCreator() { }
- internal static readonly T _instance = new T();
- }
- }
Lazy<T>()
- Lazy<Product> _product = new Lazy<Product>();
Lazy<T>(Boolean isThreadSafe)
e.g.
When lazy initialization occurs, the specified initialization function is used. Means you can pass the parameterized constructor to the Lazy<T>
e.g.
- Lazy<Product> _product = new Lazy<Product>(true);
Lazy<T>(Func<T>)
- //Initializing the category class using parametric constructor
- Lazy<Category> _category = new Lazy<Category>(() => new Category(23));
Lazy<T>(Func<T>, Boolean)
- //Initializing the category class using parametric constructor with parameter isThreadSafe
- Lazy<Category> _category = new Lazy<Category>(
- () => new Category(23), true);
Lazy<T>(LazyThreadSafetyMode)
- Lazy<Product> _product = new Lazy<Product>( System.Threading.LazyThreadSafetyMode.PublicationOnly);
Lazy<T>(Func<T>, LazyThreadSafetyMode)
- Lazy<Category> _category = new Lazy<Category>(
- () => new Category(23), System.Threading.LazyThreadSafetyMode.PublicationOnly);
Alternative to LazyInitialization System.Threading.LazyInitializer
for e.g.
Another alternative of LazyInitialization System.Threading.ThreadLocal
It is the same as Lazy<t>, but the only difference is that it stores data on Thread Local basis. So the values on each Thread would be a different copy of the Initialized object.
e.g.
You can also pass a generic delegate to pass values for a parametric constructor.
I hope this post helped you somehow understanding all support provided in .NET 4.0. So it's now up to you which approach to use and where to implement the Lazy behavior in your program or application.
- ExpensiveData _data = null;
- bool _dataInitialized = false;
- object _dataLock = new object();
- ThreadLocal<ExpensiveData> _expData = new ThreadLocal<ExpensiveData>();
- ThreadLocal<ExpensiveData> _expData = new ThreadLocal<ExpensiveData>();
- ThreadLocal<ExpensiveData> _expData = new ThreadLocal<ExpensiveData>(() =>new ExpensiveData(objectState));

Join the conversation! Your thoughts help the community grow.