Tuesday, 8 November 2011

Singleton Pattern

What is beforefieldinit?

1. All classes with static constructors will NOT be marked as 'beforefieldinit'
2. When a class is marked as 'beforefieldinit', then type initialization may be eager or lazy. So what i mean by this is

EAGER
using System;

class Test
{
public static string x = EchoAndReturn ("In type initializer");

public static string EchoAndReturn (string s)
{
Console.WriteLine (s);
return s;
}
}

class Driver
{
public static void Main()
{
Console.WriteLine("Starting Main");
// Invoke a static method on Test
Test.EchoAndReturn("Echo!");
Console.WriteLine("After echo");
// Reference a static field in Test
string y = Test.x;
// Use the value just to avoid compiler cleverness
if (y != null)
{
Console.WriteLine("After field access");
}
}
}

OUTPUT
In type initializer
Starting Main
Echo!
After echo
After field access
--------------------------------------------------
LAZY
Starting Main
Echo!
After echo
In type initializer
After field access

3. If the class 'Test' have static constructor, then only below output is possible
Main
In type initializer
Echo!
After echo
After field access

So what we understand from above points, when we have static constructor - then the type initializers called when instance/static members or functions are called on that type. If not, we can't guarantee, as type initializer might be eager or lazy.
---------------------------------------------------------------------------------
So 'readonly' fields can be initialized while declaring or in constructor, so 'static readonly' are initialized during declaration or static constructor. it also tells, reference can't be changed - means only one reference.

So

public sealed class Singleton
{
public static readonly Singleton instance = new Singleton();

static Singleton()
{
}

Singleton()
{
}
}

and

public sealed class Singleton
{
public static readonly Singleton instance;

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

Singleton()
{
}
}
------------------------------------------------------
and full lazy initialization

public sealed class Singleton
{
private Singleton()
{
}

public static Singleton Instance
{
get
{
return NestedSingleton._instance;
}
}

private class NestedSingleton
{
static NestedSingleton()
{ }

public static readonly Singleton _instance = new Singleton();
}
}

So why fully lazy initialization?
because static constructor called when static fields are initializes(bit uncontrolled), so for expensive constructor operation + better control, lazy loading is perfect

No comments: