singleton design pattern – Lazy loading

LAZY - AS LAZY AS POSSIBLE ­čÖé

  • Below test method is an issue.
  • we are just calling a static method inside singleton. But still instance get is called. we dont want to get the instance unless and untill it is required. we want it to be as lazy as possible
				
					    
        [TestMethod] 
        public void Singleton_with_only_private_and_static_constructor_static_method_invoked()
        {
            //private constructor --> static constructor --> then get --> say hello
            Singleton.hello(); 
            // you may not want to instantiate at this point of time if 
            //I am invoking a static method 
            //I want my singleton to be fully lazy
            var result1 = Singleton.Instance;
            var result2 = Singleton.Instance;
            var result3 = Singleton.Instance;
            Assert.AreEqual(1, Singleton.constructorInvokedCount);
            Assert.AreEqual(3, Singleton.instanceInvoked);
        }
				
			
				
					#nullable enable
public sealed class Singleton
{
    public static int constructorInvokedCount = 0;
    public static int instanceInvoked = 0;
    //private static Singleton? _instance;
    private static readonly Singleton instance = new Singleton();


    static Singleton()
    {
        Console.Write("Static Constructor invoked");
    }

    public static Singleton Instance { 
        get {
            instanceInvoked++;
            return instance; 
        } 
    }

    public static string hello()
    {
        return "hello";
    }

    private Singleton()
    {
        constructorInvokedCount++;
        Console.Write("Constructor invoked");
    }
    public static void Main(string[] args)
    {

    }
}
				
			
  • A private nested within a class will be useful
  • The accessebility rule in c# says – any code within this below private class is still within singleton – it can still call private constructors
  • when Singleton.hello(); is called there is no class initialization for singleton anymore it doesnt have any static variables- it has got nothing to initialize
  • var result1 = Singleton.Instance; at this point of time SingletonHolder is called,we get the instance of Singleton
				
					#nullable enable
public sealed class Singleton
{
    public static int constructorInvokedCount = 0;
    public static int instanceInvoked = 0;

    //a private nested within a class will be useful
    //The accessebility rule in c# says - any code within this below private class
    //is still within singleton - it can still call private constructors 
    //when Singleton.hello(); is called
    //there is no class initialization for singleton anymore
    //it doesnt have any static variables- it has got nothing to initialize
    //var result1 = Singleton.Instance; at this point of time SingletonHolder is called
    //we get the instance of Singleton
    private static class SingletonHolder
    {
        internal static readonly Singleton instance = new Singleton();
        static SingletonHolder()
        {

        }
    }

    public static Singleton Instance { 
        get {
            instanceInvoked++;
            return SingletonHolder.instance; 
        } 
    }

    public static string hello()
    {
        return "hello";
    }

    private Singleton()
    {
        constructorInvokedCount++;
        Console.Write("Constructor invoked");
    }
    public static void Main(string[] args)
    {

    }
}

				
			
  • Easy alternative to solution 1- use the .net 4 feature of lazy…all done and dusted, straightforward
				
					#nullable enable
public sealed class Singleton
{
    public static int constructorInvokedCount = 0;
    public static int instanceInvoked = 0;

    
    private static readonly Lazy<Singleton> lazyInstance = new Lazy<Singleton>(() => new Singleton());

    public static Singleton Instance { 
        get {
            instanceInvoked++;
            return lazyInstance.Value; 
        } 
    }

    public static string hello()
    {
        return "hello";
    }

    private Singleton()
    {
        constructorInvokedCount++;
        Console.Write("Constructor invoked");
    }
    public static void Main(string[] args)
    {

    }
}
				
			

key points

  • ┬ác# static constructors only run once per appdomain
  • ┬áStatic constructors are called when any static memeber of a type is referenced
  • ┬áStatic constructors – thread safe, no locks – good performance
  • ┬ánested class approach – complex and non-intuitive
  • ┬áLazy<T>┬á –> .net 4 2010 – Easy to use – widely used

Leave a Comment