The Singleton Pattern – Revised

While in a previous post it is explained how the singleton pattern can be implemented using double checked locking or a static constructor, .NET 4.0 provides a dedicated class Lazy<T> to support lazy initialization and the singleton pattern. This class is pretty well documented at its MSDN site , however I have found the documentation a bit over-complicated. So I would like to introduce a simpler summary of this class’s behavior.The general usage of the Lazy<T> class is pretty simple. Given a type parameter T, the Value property of an object of type Lazy<T> returns an initialized instance of T. The exact execution of the initialization process, that has a major impact in a multi-threaded environment, is controlled by the constructor parameters of the Lazy<T> class:

The effect of the isThreadSafe and mode parameters are concluded in the table below:

The constructor of the object T is called at most once, and the Value property of Lazy<T> returns the same object for all calls mode = ExecutionAndPublication,
or isThreadSafe = true
The constructor of the object T might get called multiple times, but the Value property of Lazy<T> returns the same object for all calls. (Additionally created objects are discarded.) mode = PublicationOnly
The constructor of the object T might get called multiple times, and the Value property of Lazy<T> might return different object references for different calls. mode = None,
or isThreadSafe = false


There are two interesting edge cases when Lazy<T> does not act like expected. When the valueFactory is set and whether the isThreadSafe parameter is set to false or the mode is set to None then calling the Value property might throw an InvalidOperationException with the message “ValueFactory attempted to access the Value property of this instance”. This happens when the Value property is read concurently prior having the object initialized; that is both call tries to initialize a new object of T. Note that no exception is raised when one of the threads constructs the object before the other would access the property Value. All in all, this type of uncertainty is to be avoided, so never use the Lazy<T> class in a multi-threaded environment with the isThreadSafe parameter set to false or the mode set to None.

Besides how the Lazy<T> class behaves in a multi-threaded environment, it is important to know how exceptions are handled. It is not that difficult; there are two ways of exception handling depending on the presence of the valueFactory parameter and the thread safety parameters.

Exceptions are cached valueFactory is set and mode is not PublicationOnly
Exceptions are not cached valueFactory is not set or mode is PublicationOnly


Here the important point is that with cached exceptions once the object initialization fails it is not reinvoked. All consecutive reads of Value throw the same exception. No matter if later the initialization becomes feasible, Value will never return an object.