Singleton versus static fields

A singleton is a class which only allows a single instance of itself to be created. But why do I need a whole design pattern for this? Why not simply use static fields?

singleton

Static field object gets created before the application starts

If you assign an object to a static field it gets created before the application starts even if it is never really needed. Lets imagine a class that stores an object in its static field.

  public class Globals
  {
      public static MyGlobal global = new MyGlobal();
  }

  public class MyGlobal
  {
     public MyGlobal()
     {
         Console.WriteLine("Initializing MyGlobal class");
     }
  }

I put  Console.WriteLine in the constructor of the object’s class so we can easily notice when it is triggered. We can check it easily by placing the call to Globals.global inside if block with a condition that will not be met.

    Console.WriteLine("Program begins");
    Console.WriteLine("Evaluating condition");
    if (DateTime.Today.Year == 1900)
    {
         MyGlobal myGlobal = Globals.global;
         Console.WriteLine("MyGlobal object was used");
    }
    else
    {
         Console.WriteLine("Condition not met");
    }

Here are the results:

SingletonVsStatic

MyGlobal class got initialized even though the condition was not met and Globals.global was not really called.

If we check the following:

     MyGlobal myGlobal1 = Globals.global;
     MyGlobal myGlobal2 = Globals.global;
     Assert.AreSame(myGlobal1, myGlobal2);

This test passes. Indeed, myGlobal1 and myGlobal2 will be the same instance. But what if creating the object is time consuming and there is no guarantee that it will be ever used by the application? You have to keep in mind that if you assign an object to a static field the object gets created before the application starts even if it is never really needed. That will not be efficient.

“No worries, we can use a static constructor!”

Static constructor makes the static field object not created before the application starts.

Take a look at the example with static fields once again. If I modify the Globals class and add a static constructor…

   public class Globals
    {
        static Globals()
        {
            Console.WriteLine("Static constructor of Globals class was invoked");
        }

        public static MyGlobal global = new MyGlobal();
    }

…the result in the console will be as follows:

static_constructor

The MyGlobal object was not initialized.

By default, if you assign an object to a static field the object gets created before the application starts even if it is never really needed. Explicit static constructor guarantees that the object gets created only when it is needed- lazily. Instantiation is triggered by the first reference to the static member and not at the beginning of the program.

In case the condition is met first the field will be initialized and after that the static constructor gets invoked:

static_constructor_condition_met

If there is no call to the field in our code (conditional or not):

static void Main(string[] args)
{
    Console.ReadLine();
}

the field is not initialized.

FieldNotInitialized

So what about the Singleton?

First of all, a singleton class is a class which can have its object created. A static field is just a way of creating a global variable. And that is a huge difference. Why?

  • A singleton class can inherit a different class or implement an interface.
   public class Logger: ILogger {}
  • With a singleton class unit testing is easier than with a static field. Such an object can be passed as a parameter where an interface is expected to create Dependency Injection. In unit tests it can be replaced by a stub.
  • Singleton pattern can be modified to limit the number of instances to 2 or 3 when needed. A static field does not support such a scenario.

Summary

Singleton is often called an anti-pattern. Even though it is the simplest design pattern, it needs to be implemented with care to avoid problems (for example with multi-threading). Nevertheless, in many cases it is still better than a static field. It provides some benefits of object oriented programming while a static field is just a  way of creating a global variable.

References

http://www.pzielinski.com/?p=1137

Head First Design Patterns” Elisabeth Freeman, Kathy Sierra

Leave a comment