The singleton pattern VS static classes - Reyn's Blog
in

dotnet.org.za

South African .NET Developer Portal

Reyn's Blog

Divide and Conquer !
Remember, pain is just fear leaving your body !

The singleton pattern VS static classes

I was attending the “Microsoft patterns and practices” lectures the other day when the subject of the singleton pattern came up.

 

One of the questions a friend asked, which weren’t discussed at the time, was: “Why would I want to use the singleton pattern when I can simply declare all the methods and variables in my class as static?”

 

Well, of course you can. If you have a self contained class that doesn’t have any special initialization. Something like:

 

public class Test1

{

      static int someValue = 100;

 

      static public int someMethod()

      {

            return someValue;

      }

 

      static Test1()

      {

            System.Console.WriteLine(“Test1 static constructor”);

      }

}

 

Test1 is a simple self contained class with a static constructor. The static constructor will be called right before the first use of the static class.

 

So if we have something like:

System.Console.WriteLine("First Line");

System.Console.WriteLine(Test1.someMethod());

The output will be: 

First Line

Test1 static constructor

100

 

You might have already spotted the problem with static classes, copy and paste the following code into your IDE, check if you can see what the output should be before running it:

 

      public class A

      {

            public static string staticVariableCopiedFromB = B.staticVariable;

            public static string staticVariable = "Thing is a string defined in A";

      }

 

      public class B

      {

            public static string staticVariableCopiedFromA = A.staticVariable;

            public static string staticVariable = "Thing is a string defined in B";

      }

 

      public class Test

      {

            static void Main(string[] args)

            {

                  System.Console.WriteLine(A.staticVariableCopiedFromB);                 

                  System.Console.WriteLine(B.staticVariableCopiedFromA);

            }

      }

 

The output you should get is:

 

Thing is a string defined in B

 

Why is this happening? Lets look at what the JIT compiler is doing:

 

  1. A is being called, so start initializing A
  2. The static variable in A needs a value from B, so start initializing B
  3. B needs a static value in A, which isn’t set yet

 

This prevents infinite circular initialization.

 

Changing the order so that the string assignment happens before the static assignment from the other class resolves the issue:

 

      public class A

      {

            public static string staticVariable = "Thing is a string defined in A";

            public static string staticVariableCopiedFromB = B.staticVariable;

      }

 

      public class B

      {

            public static string staticVariable = "Thing is a string defined in B";

            public static string staticVariableCopiedFromA = A.staticVariable;

      }

 

An even better way is to use the static constructor to explicitly initialize it in the correct order:

 

      public class A

      {

            public static string staticVariable;

            public static string staticVariableCopiedFromB;

            static A()

            {

                  staticVariable = "Thing is a string defined in A";

                  staticVariableCopiedFromB = B.staticVariable;              

            }

      }

 

      public class B

      {

            public static string staticVariable;

            public static string staticVariableCopiedFromA;

            static B()

            {

                  staticVariable = "Thing is a string defined in B";

                  staticVariableCopiedFromA = A.staticVariable;

            }

      }

 

The compiler will actually generate the static constructors itself; it just feels safer to do it explicitly.

 

That might have been an elegant solution for a very small example, but can you see what will happen when we start working with 5 or more classes with dependencies.

 

This is why we can’t always depend on the order of static initialization. By explicitly initializing our singleton classes we can be sure that someone doesn’t destroy our carefully crafted static initialization bootstrap code by accidentally calling something when it shouldn’t be. As you can see, there isn’t a compile or run time error, just an unexpected result, these problems can be very difficult to track down.

 

Please drop a comment if I’m missing something or unaware of a dot net specific feature.

Published Jul 07 2004, 12:27 AM by reyn
Filed under:

Comments

 

pieter said:

Coolstuff reyn, a very simple explanation which will surely make it easier for certain people to understand.
July 8, 2004 2:41 PM
 

Anton Clarke said:

I'm afraid the example you give whilst interesting does not properly explain the situation. Initialisation order during instantiation is an important problem but you have instead demonstated the henious crime of co-dependant classes.

You did correctly point out the choice of static vs singleton classes is one of decisions over initialisation; singletons allow greater freedom and fluidity, especially in the case of systems where the you will derive from the singleton class and/or the user will make frequent changes to the values of the singleton. Static classes are particularly useful were they access data that is truely static or where the values are mapped from some external source that may not be set by the user - e.g. the static class may get the current instantaneous oil pressure or water temperature from a car engine.

However, your example is an excellent way to explain why no-one should write co-dependant classes.

If I see anyone creating co-dependant classes like this I reach for my light-sabre (ok, my sturn look).
August 5, 2005 11:36 PM
 

reyn said:

This blog was about what the compiler allows you, not about good practices.
June 21, 2006 11:01 AM
 

Natalia Burina's Technical Blog said:

We are working on design for my current project. There is a situation where we need one and only...

October 29, 2006 9:52 PM
 

Object_oriented said:

This is good to know the problem with initialisation and it would be better if can give us with some more examples .

February 22, 2008 12:37 PM
 

Nitin Agrawal said:

I can highlight one benefit of Singletone pattern over a class having all the variables an methods defined as static:

Static class’ methods can access only static variables.

Consider the situation in which u want to serialize your singletone class.

If u follow t the Singleton pattern then all the variables will be serialized that are defined as non static variable.

But you can’t achieve this task with Static class by using default serializable mechanism coz static variable do not participate in serialization. You will have to extend ur class from externalizable interface

May 15, 2008 10:03 AM

Leave a Comment

(required)  
(optional)
(required)  

Enter the numbers above:
Add
Powered by Community Server (Commercial Edition), by Telligent Systems