Singleton (C#)

This week I was asked a question regarding the singleton pattern and I went blank, it has been a while since I have even thought about the concept, this was extremely embarrassing considering how fundamental the pattern is for computer science. So as always this blog serves as a public way of reminding myself that there is always something to learn and even more to remember.

So the concept of a singleton revolves around the idea that you want to ensure that an object should be restricted to one instance of itself . This may be because you are trying to create an object that manages other objects on a global basis within your project.

There a two main principles that go into the singleton. First, we need some mechanism by which we ensure that there is a single object created. Secondly, you have to control the constructor (using private/protected keywords) so at no point after the initial creation of the object can someone perform a create new instances of your class.

The following is the most rudimentary form of the singleton pattern that I could come up with, the 'public static readonly' keywords ensure that when we create an object the uno member is only created once (readonly). While this solves the problem, there are those engineers among us who would complain that the design of the class forces the immediate creation of a static MySingleton object because the 'new' function is not restricted to a method call or the constructor.

public class MySingleton
{
public static readonly MySingleton uno = new MySingleton();
private MySingleton()
{
}
}
public class MySingleton { public static readonly MySingleton uno = new MySingleton(); private MySingleton() { } }
public class MySingleton
{
	public static readonly MySingleton uno = new MySingleton();

	private MySingleton()
	{

	}
}

The following example builds upon the weakness of the first in that the instantiation of the object does not occur until requested in the Instance method, as a result the public static singleton object has become private. The Instance method now verifies if uno is null and returns it accordingly.

public class My2ndSingleton
{
private static My2ndSingleton uno;
private My2ndSingleton()
{
}
public My2ndSingleton Instance()
{
if (uno == null)
uno = new My2ndSingleton();
return uno;
}
}
public class My2ndSingleton { private static My2ndSingleton uno; private My2ndSingleton() { } public My2ndSingleton Instance() { if (uno == null) uno = new My2ndSingleton(); return uno; } }
public class My2ndSingleton
{
	private static My2ndSingleton uno;

	private My2ndSingleton()
	{

	}

	public My2ndSingleton Instance()
	{
		if (uno == null)
			uno = new My2ndSingleton();

		return uno; 
	}
}

The final Singleton scenario accounts for multithreaded applications and provides a standard lock() with a double check to create a critical section around the uno instance. We actually have two verifications (double check) for uno being null, the first check ensures that we do not use the lock unnecessarily , the  second check is conducted after the lock is created to ensure that no other thread snuck in just before the lock.

public class My3rdSingleton
{
private static My3rdSingleton uno;
private static object sync = new object();
private My3rdSingleton() { }
public My3rdSingleton Instance()
{
if (uno == null)
{
lock (sync)
{
if (uno == null)
{
uno = new My3rdSingleton();
}
}
}
return uno;
}
}
public class My3rdSingleton { private static My3rdSingleton uno; private static object sync = new object(); private My3rdSingleton() { } public My3rdSingleton Instance() { if (uno == null) { lock (sync) { if (uno == null) { uno = new My3rdSingleton(); } } } return uno; } }
public class My3rdSingleton
{
	private static My3rdSingleton uno;
	private static object sync = new object();

	private My3rdSingleton() { }

	public My3rdSingleton Instance()
	{
		if (uno == null)
		{
			lock (sync)
			{
				if (uno == null)
				{
					uno = new My3rdSingleton();
				}
			}
		}

		return uno;
	}
}

May I never forget this again...

Technorati tags: ,


Comment Section

Comments are closed.