C#: if sealed is supported then why not singleton
As I had said in my previous blog "Usefulness of a new feature is best understood if you try to implement something that the feature targets without using that feature". Lets take the example of the sealed class modifier. A sealed class cannot be inherited. The following code fails to compile with the error "cannot derive from sealed type Sealed.MyClass"
sealed class MyClass{ public string name = "Abhinaba";}class AnotherClass : MyClass // compilation failure{}
The whole functionality of making a class non-inheritable comes from a single keyword sealed. This is what I love about C#. The language-designers took the care of incorporating common design patterns into the language. In C++ these simple things are missing. See what the Stroustrup has to say about it here. In C++ to get the same effect as in sealed C# class we need to do the following
// forward declarationclass NotInheritable; // This is the lockstruct Prot{private: // This does the trick Prot(){}; Prot(const Prot& p){}; // The class that you want to lock friend class NotInheritable;};// Inherit from the lock (have to use virtual) and // This class will become un-inheritable :)class NotInheritable : virtual public Prot{public: NotInheritable() { cout << "Can create object" << endl; }};// Try the impossible and you will failclass TryToInherit : public NotInheritable{public: TryToInherit() { cout << "Successful in inheriting from TryToInherit" << endl; }};
The trick here is to inherit your class from another class which has the constructor as private. This whole lot of work gets done easily using the sealed keyword in C#.
Singleton
When I saw the sealed keyword in C# one of the first things that occured to me is why singleton in not similiarly supported in C#. The singleton design pattern restricts the instantiation of a class to one object. In some cases the definition of singleton has got extended and is defined as just restricting the number of instances of a class. So the former definition is a special case (where the number is 1) of the extended definition.
In C# one way to create singleton classes is as follows
using System;public class Singleton{ private static Singleton instance; private Singleton() { } public static Singleton Instance { get { if (instance == null) { instance = new Singleton(); } return instance; } }}
The advantage of this implementation is that this is true lazy instantiation as the instance is created only when asked for. However, this is NOT at all thread safe. If more than one thread try to create the object and enter the Instance accessor then due to a race-condition both may evaluate instance == null to true and create more than one objects.
Other than using the lock and the double-check-locking I prefer to use the static instantiation which is not so lazy but is thread-safe in C#. This goes as follows
public class Singleton{ private static readonly Singleton instance = new Singleton(); // makes the class NOT marked with beforeFieldInit static Singleton() { }
Singleton() { } public static Singleton Instance { get { return instance; } }}
This is thread-safe as it is garaunteed that the static ctor will be executed only once per AppDomain. Its not lazy because if you have any other static fields then an access to it will trigger the creation of the instance. Even though coding up singleton is easy, it would enhance readability and also save some typing (and same some people from CTS) is the following was equally supported in C#
public singleton class MyClass{ // ...}
Either the compiler could emit code in the same pattern or internally ensure that only one instance is created using something like reference counting.
Comments
- Anonymous
December 06, 2005
Isn't the more obvious answer a snippet? So you type sing<tab> and it spits out that? - Anonymous
December 06, 2005
Nice! Especially if functionality is added so that singleton types can be identified by reflection - Anonymous
December 06, 2005
Snippet should be super-cool. It does not break anything saves me of CTS and everyone is happy. Other than the guys using non VS IDE :)
However, I always think that editor niceties are not substitutes for true language features... Only adding keywords can enhance readability and as Neil wanted, the info will also be available via reflection!!! - Anonymous
December 07, 2005
Isn't it that MS wants to encourage the Service Oriented Architecture, so they'd rather we use an IServiceProvider where we might otherwise use Singleton? - Anonymous
December 07, 2005
What's the difference between having a class as a singleton, or just exposing all of the class' members and methods as static, and declaring the class static. Then you'll only have one instance of it, which will be instantiated automatically before first use.
Mat - Anonymous
December 07, 2005
I like the idea of a "singleton" keyword because it makes it perfectly clear the intention of the programmer. This is much better than having to recognize one of a few possibilities of a coding pattern. - Anonymous
December 07, 2005
I don't think this will work out as you think. What if the type of the singleton needs to be determined at run-time? Also your singleton keyword makes it impossible to write unit-tests. In this case you create a new instance of the singleton object before every test. - Anonymous
December 07, 2005
"What's the difference between having a class as a singleton, or just exposing all of the class' members and methods as static, and declaring the class static. Then you'll only have one instance of it, which will be instantiated automatically before first use." - Mat
When remoting objects, static methods are executed on the client and not the server. - Anonymous
December 07, 2005
The comment has been removed - Anonymous
December 07, 2005
Max:
Perhaps add some disposal semantics which internally dispose and re-create the object?
Really, singleton shouldn't be compiler magic. It should be a CLR feature, and it should be defineable at several levels: thread, appdomain, machine, subnet, etc. - Anonymous
December 07, 2005
Sounds like a good idea. For thread level singletons, one can do ThreadStaticAttribute. For AppDomain, well, the scope of Types end at the appdomain as long as the assembly isn't domain neutral. Machine level, I guess u can use mutexes. Subnet.... Is it really necessary? =] - Anonymous
December 07, 2005
As tzagotta highlighted it, my point is that adding the keyword makes the intention clear. Yes static classes may work (with remoting limitation) and yes code snippet will work too. But none of this will call out to the code maintainer or to the person writing a client the intention of the class. With compiler and CLR support this info will be available through reflection as well. - Anonymous
May 16, 2006
I have two classes (like TAccount and TInvoices) defined like this in c#:
public class TAccount
{
// constructor
public Taccount
{
}
// property of type TInvoices!!
// TInvoices is not defined yet...!??
public TInvoices invoices;
}
public class TInvoices
{
// constructor
public TInvoices
{
}
public TAccount account;
}
How can i make a forward declaration of TInvoices here??
thank you for responding me to
eleoui_mustafa@yahoo.com