On managed something and graphical nonsense

Monday, February 20, 2006

Fun with Singletons in C# 2.0 (Part 1)

Introduction
Coming from a hardcore C++ development background, I had amazed myself several times reading such excelent books like Modern C++ Design: Generic Programming and Design Patterns Applied from Andrei Alexandrescu or the source code of Boost. They are extremely hard to understand (took me several weeks and a big headache to get a glipse of what he was talking about) but I would recommend them anytime to C# developers that would really want to uncover the real potential of C# generics.

With the new generics support given by C# 2.0 some common design patterns can be generalized to work with any type. Exploiting the capabilities given by the type system, reflection and generics we can accomplish typesafe modular code customization and automation. Fun with Singletons is just a demostration among the array of posibilities that C# 2.0 features introduce.

The audience for this article is anyone with a decent knowledge on generics, however to really appreciate it, an exposure to C++ templates engine would be desired.

Background

The singleton is by far the most common design pattern in literature, it has been implemented countless of times in several languages. In C# the typical implementation requires us to implement the Instance method and be aware of locking depending if we are creating it lazily or statically.

One night (like 8 months ago) I asked to myself: Wouldnt it be nice to inherit from a class and automatically have the singleton implementation done? And what about all security controls required to make sure I am not making a mistake in the implementation of my class?

The response didnt took much time to come: yes, I can do that in C++; however, the aim was to do it to investigate one of those interesting features back then with the Beta 2 of Visual Studio 2005, C# generics. The solution was heavily inspired by Alexandrescu's Generic Singleton Pattern also known as "Allocator Based Singleton". And here we go :) .

Generic Singletons

At the time I had been looking to code the singletons in a way that they could be used like this:

public class MySingleton : Singleton<MySingleton>
{}

Luckily up to that point C# generics suffice to handle a situation like that one, so after some time trying to get a grasp of how generics worked in C# 2.0 I came up with the following Singleton class.

public class Singleton<T> where T : new ()
{
private static T instance;

public static T Instance { get { return instance; } }

static Singleton ()
{
instance = new T();
}

protected Singleton ()
{}
}

public class MySingleton : Singleton<MySingleton>
{
public MySingleton ()
{}
}

At the time I was thrilled, I was able to create a singleton using the famous recursive pattern that made C++ templates so weird to understand; all that in C# 2.0. However, I wasnt entirely satisfied with the implementation. So where's the catch? Read the code again :).

One of the tenets for the Singleton pattern existence is that the instance must be unique; that was the property that I wasnt honoring. The requirement that T must implement a public default constructor was killing the design of such a reusable pattern component. Took me like 6 hours of trying this and that to realize that the design wasnt flawed, it was my usual C++ style of thinking what was hindering me from discovering the solution to this problem.

The solution can be described with just one word: Reflection. Yes, reflection is one of those features that can be extremely powerful when used correctly or a "Golden Hammer" if used obsesibly. In this case, reflection was the feature that would allow me to honor the most important property of Singletons and at the same time do some runtime checking on behalf of the user of a generic library.

ConstructorInfo constructor = typeof(T).GetConstructor(
BindingFlags.Instance | BindingFlags.NonPublic,
null, new Type[0],
new ParameterModifier[0] );
if (constructor == null)
throw new Exception(
"The singleton doesnt have a private
/protected constructor."
);

try
{
allocator = constructor.Invoke(new object[0]) as T;
}
catch (Exception e)
{
throw new Exception(
"The Singleton couldnt be constructed", e
);
}
Now instead of relaying on the new() constrain in the generic type, by reflection we would only look for private or protected constructions. That means that, if the user mistakenly try to create a singleton and add a default constructor that isnt private or protected, then the singleton base would not allow it to continue raising an exception ( this implementation do not check if the user adds public constructors with parameters, but that is easily achived ).

Up to that point I was pretty satisfied with the solution, but having different styles of singletons behaviors like Lazy allocation, configuration based, etc; would require me to recode the singletons. I know what you think, I dont like it either :D

Next part of this post will show how to accomplish the highly desired (by me at least) "Allocator Based Singleton" and the complete source of its implementation. So, see ya arround.

Greetings
Federico Lois

2 Comments:

  • I have found your discussion of singletons very interesting an potentially useful but I am confused. You have posted the code here in the clear without any restrictions and you have posted it on CodeProject with a very peculiar disclaimer "disclosure or use of the code is forbiden".

    First of all, if you aren't allowed to use the code, does that mean that you can't read it (a form of use)?

    Secondly, it's the thought that counts, not the code. You clearly wanted to expose your thoughts publicly, so having done that why restrict people from benefitting from your wisdom.

    Thirdly, changing a few of the names changes the code. The copyright only applies to the words, not the concepts, and you can't copyright the C# words since they are placed in the public domain by ECMA, so a trivial name change of the variables would create different code that is not protected by the copyright annotation.

    So - if your objective was to be helpful to the community of C# users, and since you have essentially released the code by posting it in your blog, why attach a vague and probably unenforcable clause to the code posted on CodeProject?

    I hope that you don't mind by nit-picking, it comes from years of thinking like a compiler:) and I do appreciate your efforts.

    By Blogger Dan Essin, At 9:48 PM  

  • That was an unfortunate error on my part, that was added because that code originally was in one of my libraries for a project and forgot to remove it.

    The idea to leave it in the open was for anyone to use it, I will be correcting it in Code Project too.

    About renaming the variables it is not entirely true that the code will be different ;), but that is another story :).

    By Blogger Federico Lois, At 11:10 AM  

Post a Comment

Subscribe to Post Comments [Atom]



<< Home