Following my earlier post
on instance constructors, I am going to cover the "Type Initialisers" this
time.
Unlike instance constructors, which are created by the compiler if none is defined
by the developer, types do not necessarily have an initialiser. Let's have
a look at our first example. The following screenshot shows how the details of the
ApplicationController class are displayed in
Ildasm.
public
class ApplicationController
{
private static
ApplicationController instance;
}

Type initialiser is mapped to the .cctor method (instance constructors are
mapped to .ctor). Since the ApplicationController class does not have
any type initialiser (inline static field initialiser or static constructor), .cctor
is not generated. The compiler emits the .cctor only if there are
any inline static field initialisers or if the developer has defined a static
constructor for the class.
public
class ApplicationController
{
private static
ApplicationController instance =
new ApplicationController ();
}
We have now added a static field initialiser to the ApplicationController class so
Ildasm shows the .cctor statement, which represents the type initialiser.

And this is the generated IL code:
.method private
hidebysig specialname rtspecialname static
void .cctor()
cil managed
{
// Code size 11 (0xb)
.maxstack 8
IL_0000: newobj instance void StaticConstructorSample.ApplicationController::.ctor()
IL_0005: stsfld class StaticConstructorSample.ApplicationController
StaticConstructorSample.ApplicationController::'instance'
IL_000a: ret
} // end of method ApplicationController::.cctor
As you may notice, static constructors are private (so that only CLR can call them) and
you cannot specify any access modifier for the static constructor. Each type
can have only one static constructor, which has to be parameter-less. It is good
to know that both value types and reference types can have type initialisers.
Note: You can actually force the type initialiser for a specific type to be executed
by calling the
RunClassConstructor method on System.Runtime.CompilerServices.RuntimeHelpers.
If a type has both inline static field initialisers and a static constructor,
the compiler will inject the inline static field initialisers (in the textual
order in which they appear in the type declaration) at the beginning of
the type initialiser. Inline static field initialisers can reference other static
members (static properties, methods or fields). The compiler then
emits the code for the static constructor as defined by the type author.
The following example shows how this works:
public
class ApplicationController
{
private static
ApplicationController instance =
new ApplicationController();
private static
Dictionary<string,
object> cache = null;
static ApplicationController()
{
Console.WriteLine("Type ApplicationController initialised.");
}
------------------------
.method private hidebysig specialname rtspecialname static
void .cctor()
cil managed
{
// Code size 30 (0x1e)
.maxstack 8
IL_0000: newobj instance void StaticConstructorSample.ApplicationController::.ctor()
IL_0005: stsfld class StaticConstructorSample.ApplicationController
StaticConstructorSample.ApplicationController::'instance'
IL_000a: ldnull
IL_000b: stsfld class [mscorlib]System.Collections.Generic.Dictionary`2<string,object>
StaticConstructorSample.ApplicationController::cache
IL_0010: nop
IL_0011: ldstr "Type ApplicationController
initialised."
IL_0016: call void [mscorlib]System.Console::WriteLine(string)
IL_001b: nop
IL_001c: nop
IL_001d: ret
} // end of method ApplicationController::.cctor
If a type does not have a static constructor, the compiler marks the type with "beforefieldinit". This
allows the CLR to perform a lazy initialisation on that type. This means the CLR has
the option of not running the type initialiser until the first
access to any static field of the type. So accessing an instance
member does not necessarily result in execution of the type initialiser (unless
that instance member references a static field of that type).
Let's revisit our earlier example where we did not have a static constructor
and see how the ApplicationController class is compiled to the IL code:
public
class ApplicationController
{
private
static
ApplicationController instance
= new
ApplicationController();
}
------------------------
.class public auto ansi beforefieldinit
StaticConstructorSample.ApplicationController
extends [mscorlib]System.Object
{
} // end of class StaticConstructorSample.ApplicationController
However, if the type has a static constructor (even if it is empty), the compiler
will not mark the class with "beforefieldinit". The impact is that the
type initialiser will run just before the very first access to either instance or
type members of the type. This means the CLR has to make sure the type
initialiser is called before any access to the type in the current application domain.
public
class ApplicationController
{
private
static
ApplicationController instance
= new
ApplicationController();
// This will prevent the compiler
from emitting [beforefieldinit] for this class
static
ApplicationController()
{
}
}
------------------------
.class public auto ansi StaticConstructorSample.ApplicationController
extends [mscorlib]System.Object
{
} // end of class StaticConstructorSample.ApplicationController
As you can see, "beforefieldinit" is missing from the IL code this time. There is
currently no way for C# developers to specify whether "beforefieldinit" should be
emitted for a specific type. The C# compiler just looks for the static constructor
for the type and if it finds it, it does not mark the type as "beforefieldinit".
Otherwise, it will mark the type as "beforefieldinit".
The Standard
ECMA-335 [page 37] accurately defines the semantics for executing the
type initialiser:
The semantics of when and what triggers execution of such type initialization methods,
is as follows:
1. A type can have a type-initializer method, or not.
2. A type can be specified as having a relaxed semantic for its type-initializer
method (for
convenience below, we call this relaxed semantic BeforeFieldInit).
3. If marked BeforeFieldInit then the type’s initializer method is executed at,
or sometime before,
first access to any static field defined for that type.
4. If not marked BeforeFieldInit then that type’s initializer method is executed
at (i.e., is triggered
by):
• first access to any static field of that type, or
• first invocation of any static method of that type or
• first invocation of any constructor for that type.
5. Execution of any type's initializer method will not trigger automatic execution
of any initializer
methods defined by its base type, nor of any interfaces that the type implements
One may ask how the compiler knows whether the type initialiser is run
in the current application domain already? Well, it doesn't because it
can't. This is the responsibility of the JIT compiler to emit a call to the type
initialiser if it is not executed in the current application domain. As you can
imagine, this can be costly in terms of performance so if static field initialisers
satisfy your requirements, do not create a static constructor for your type.
Since static constructors are visible to all threads in the current application
domain, it is possible that code in more than one thread force the type to be initialised
but CLR has to make sure the type initialiser is run only once. In order to do this,
the calling thread acquires a synchronisation lock on that type and only the
first call to the type constructor actually results in execution of the
constructor. All other threads will notice that the constructor has already been
executed. The way the CLR deals with concurrent access to the type initialiser provides
an easy and safe way of implementing the
Singleton pattern.