Thread Safe Singleton using Lazy Loading

Creating a thread-safe singleton in C# using lazy loading is a common design pattern that ensures that a class has only one instance while providing a global point of access to it.

We have discussed lazy loading concept with the help of single lock and double lock in previous lessons, and in previous lesson, we have discussed about Eager Loading, where the instance creation is done at the starting of the applications, making the instance available at the initial stage.

With C# 4.0 onwards, we can use the Lazy Generic class to make the Singleton Instance Lazy Loading. Here the instance is only created when it is first accessed which further helps in improving the performance of application. Let us proceed and see how we can implement Lazy Loading in the Singleton Design Pattern using the Lazy Generic Class in C#


Example of Lazy loading with Lazy keyword

public class Singleton
{
    // The private constructor ensures that the class cannot be instantiated from outside.
    private Singleton() 
    {
        // Initialization code
    }

    // The Lazy instance will create the Singleton instance on first access.
    private static readonly Lazy<Singleton> _instance = new Lazy<Singleton>(() => new Singleton());

    // Public property to provide access to the instance.
    public static Singleton Instance 
    {
	return _instance.Value;
    }

    // Example method
    public void DoSomething()
    {
        // Method implementation
    }
}
class Program
{
    static void Main(string[] args)
    {
        // Access the Singleton instance
        Singleton singleton = Singleton.Instance;
        singleton.DoSomething();
    }
}

Benefits of the Lazy loading with Lazy keyword

  • Thread Safety: The Lazy ensures that the singleton instance is created in a thread-safe manner without requiring explicit locking.

  • Lazy Initialization: The instance is only created when it is first accessed.

  • Simplicity: The implementation is straightforward and easy to understand.

The Lazy Generic Class, introduced as part of .NET Framework 4.0, provides built-in support for lazy initialization, i.e., on-demand object initialization. If you want to make an object (such as Singleton) lazily initialized, i.e., on-demand object initialization. You need to pass the type (Singleton) of the object to the Lazy generic class. Within the Lazy constructor, using the lambda expression, we need to create the instance, which is shown below.


Lazy<Singleton> _instance = new Lazy<Singleton>(() => new Singleton());


Conclusion

The best practice for implementing a thread-safe singleton in C# is to use the Lazy approach, which provides both lazy initialization and thread safety with minimal overhead. Avoid basic checks for null and inefficient locking mechanisms, as these can lead to errors or performance issues in multi-threaded environments.