Singleton redundancy
At home I code a lot of singleton classes. Most of this code is boilerplate code that I just write over and over again. Originally I thought that generics would solve this problem. I planned to write a generic singelton of the following form.
public
class Singleton<T,K> : K
{
public static T Instance
{
// ... Singleton code
}
}
public class MyFactory : Singleton<MyFactory,MyBaseFactoryClass>
{
}
Unfortunately that doesn't work because generics in .NET do not support inheritance of that kind (AFAIK). This forced me to find a different route. I decided to code a generic singleton class that operated on static methods. I wanted to get the behavior below.
public class MyFactory
{
public static MyFactory Instance
{
get
{
return Singleton<MyFactory>.GetInstance();
}
}
}
This still didn't solve my problems because this requires that MyFactory have a public constructor. I had to settle for this instead.
public class MyFactory
{
public static MyFactory Instance
{
get
{
return Singleton<MyFactory>.GetInstance(delegate() { return new MyFactory(); } );
}
}
}
This makes it very simple to create per process singleton classes. It's not quite as easy as my original idea but it gets the job done and removes a lot of redundant code. Here's the code that I'm using for my Singleton<T> class.
public
static class Singleton<T>
{
public delegate T SingletonCreation();
private static T _instance;
public static T GetInstance(SingletonCreation del)
{
if (_instance == null)
{
lock (typeof(Singleton<T>))
{
if (_instance == null)
{
T temp = del();
System.Threading.Thread.MemoryBarrier();
_instance = temp;
}
}
}
return _instance;
}
}
For more information on singletons in .NET check out this great entry by Brad Abrams https://blogs.msdn.com/brada/archive/2004/05/12/130935.aspx
MSFT disclaimer: This posting is provided "AS IS" with no warranties, and confers no rights.
Comments
Anonymous
November 28, 2004
Blog link of the week 48Anonymous
December 07, 2004
You still need a memory barrier on the read path. If _instance is not null the data fields in the object may still reflect the cached values. Just give-up on the double locking pattern and always lock before checking _instance.
(Also don't lock on typeof(T) - add a static object _syncobj to lock on.Anonymous
December 07, 2004
I understand the point you're making about locking on typeof(). But in this case I felt it was safe because the who else wants to lock Singleton<MyType>? If they do then they're setting themselves up for errors.
I don't understand you're point about the memory barriers on the read operation. Can you elaborate further?Anonymous
September 04, 2007
Quite awhile back I posted about how to create a re-usable singleton pattern in .Net. Link is here .Anonymous
September 04, 2007
PingBack from http://msdnrss.thecoderblogs.com/2007/09/04/singleton-pattern/