I want to figure out about singleton pattern designs. I want to create seperated instances for per thread from my singleton class. So I provided two designs below.
It is Working
class Program
{
static void Main(string[] args)
{
Task.Factory.StartNew(() => Console.WriteLine(SingletonClass.Instance.GetHashCode()));
Task.Factory.StartNew(() => Console.WriteLine(SingletonClass.Instance.GetHashCode()));
Console.ReadLine();
}
}
public sealed class SingletonClass
{
[ThreadStatic]
private static SingletonClass _instance;
public static SingletonClass Instance
{
get
{
if (_instance == null)
{
_instance = new SingletonClass();
}
return _instance;
}
}
private SingletonClass()
{
}
}
It is not working (Throwing NullReferenceException and instance is not being created.)
class Program
{
static void Main(string[] args)
{
Task.Factory.StartNew(() => Console.WriteLine(SingletonClass.Instance.GetHashCode()));
Task.Factory.StartNew(() => Console.WriteLine(SingletonClass.Instance.GetHashCode()));
Console.ReadLine();
}
}
public sealed class SingletonClass
{
[ThreadStatic]
private static SingletonClass _instance = new SingletonClass();
public static SingletonClass Instance
{
get
{
return _instance;
}
}
private SingletonClass()
{
}
}
I am really wondering why an instance is not created for second design. Can anybody explain that please ?
The answer to your question is mostly related to how class fields are initialized.
In the second example, the
_instancefield is initialized at declaration. Every time a static field is initialized at declaration, a static constructor will be created (if you don't have it declared already). At compile time, the initialization will be moved into the static constructor. This means that you will end up having something like this (didn't copy the IL code as it would be harder to understand):The CLR ensures that the static constructor is called only once, regardless of how many threads you have. Looking at the above code, it means that for the two Tasks that you created, the
_instancefield will be initialized only once (since there will be only one call to the static constructor).