Module Initializer (a.k.a Module Constructor)
Module Initializer (a.k.a Module Constructor)
CLR v1.0/v1.1 supports Type Initializer. Here is a quote from ECMA-335: CLR Partition II Metadata and File Format:
1.1.1 Type initializer
A type (class, interface, or value type) can contain a special method called a type initializer, which is used to initialize the type itself. This method shall be static, take no parameters, return no value, be marked with rtspecialname and specialname, and be named .cctor.
Like instance constructors, type initializers can write into static fields of their type that are marked with the initonly attribute.
[Example: The following shows the definition of a type initializer:
.class public EngineeringData extends [mscorlib]System.Object
{
.field private static initonly float64[] coefficient
.method private specialname rtspecialname static void .cctor() cil managed
{
.maxstack 1// allocate array of 4 Double
ldc.i4.4
newarr [mscorlib]System.Double
// point initonly field to new array
stsfld float64[] EngineeringData::coefficient
// code to initialize array elements goes here
ret
}
}end example]
[Note: Type initializers are often simple methods that initialize the type’s static fields from stored constants or via simple computations. There are, however, no limitations on what code is permitted in a type initializer. end note]
1.1.1.1 Type initialization guarantees
The CLI shall provide the following guarantees regarding type initialization:
1. As to when type initializers are executed is specified in Partition I.
2. A type initializer shall be executed exactly once for any given type, unless explicitly called by user code.
3. No methods other than those called directly or indirectly from the type initializer are able to access members of a type before its initializer completes execution.
CLR v2.0 introduces Module Initializer. It is very similar to type initializer, with the difference that the module initializer is associated with a module, instead of a type. Since the module initializer is not associated with any type, it is a global function.
The following describes module initializer.
1.1.2 Module Initializer
Modules may contain special methods called module initializers to initialize the module itself.
All modules may have a module initializer. This method shall be static, a member of the module, take no parameters, return no value, be marked with rtspecialname and specialname, and be named .cctor.
There are no limitations on what code is permitted in a module initializer. Module initializers are permitted to run and call both managed and unmanaged code.
1.1.2.1 Module Initialization Guarantees
The CLI shall provide the following guarantees regarding module initialization:
1. The semantics of when, and what triggers execution of module initialization methods, is as follows:
A. A module may have a module initializer method, or not.
B. The module’s initializer method is executed at, or sometime before, first access to any types, methods, or data defined in the module
2. A module initializer shall run exactly once for any given module, unless explicitly called by user code
3. No method other than those called directly or indirectly from the module initializer will be able to access the types, methods, or data in a module before its initializer completes execution.
Since C# does not support global functions, C# does not support module initializer.
C++/CLI internally uses module initializer, as described in the MSDN VC++ chat script. (https://msdn.microsoft.com/chats/transcripts/vstudio/vstudio_091604.aspx)
The following is the ildasm output of the module initializer of msvcm80.dll.
.method assembly specialname rtspecialname static
void .cctor() cil managed
{
.custom instance void [mscorlib]System.Diagnostics.DebuggerStepThroughAttribute::.ctor() = ( 01 00 00 00 )
// Code size 39 (0x27)
.maxstack 2
.locals ([0] valuetype '<CrtImplementationDetails>'.LanguageSupport languageSupport)
IL_0000: ldloca.s languageSupport
IL_0002: call valuetype '<CrtImplementationDetails>'.LanguageSupport* modopt([mscorlib]System.Runtime.CompilerServices.CallConvThiscall) '<CrtImplementationDetails>.LanguageSupport.{ctor}'(valuetype '<CrtImplementationDetails>'.LanguageSupport* modopt([mscorlib]System.Runtime.CompilerServices.IsConst) modopt([mscorlib]System.Runtime.CompilerServices.IsConst))
IL_0007: pop
.try
{
IL_0008: ldloca.s languageSupport
IL_000a: call void modopt([mscorlib]System.Runtime.CompilerServices.CallConvThiscall) '<CrtImplementationDetails>.LanguageSupport.Initialize'(valuetype '<CrtImplementationDetails>'.LanguageSupport* modopt([mscorlib]System.Runtime.CompilerServices.IsConst) modopt([mscorlib]System.Runtime.CompilerServices.IsConst))
IL_000f: leave.s IL_001f
} // end .try
fault
{
IL_0011: ldftn void modopt([mscorlib]System.Runtime.CompilerServices.CallConvThiscall) '<CrtImplementationDetails>.LanguageSupport.{dtor}'(valuetype '<CrtImplementationDetails>'.LanguageSupport* modopt([mscorlib]System.Runtime.CompilerServices.IsConst) modopt([mscorlib]System.Runtime.CompilerServices.IsConst))
IL_0017: ldloca.s languageSupport
IL_0019: call void ___CxxCallUnwindDtor(method void *(void*),
void*)
IL_001e: endfinally
} // end handler
IL_001f: ldloca.s languageSupport
IL_0021: call void modopt([mscorlib]System.Runtime.CompilerServices.CallConvThiscall) 'gcroot<System::String ^>.{dtor}'(valuetype 'gcroot<System::String ^>'* modopt([mscorlib]System.Runtime.CompilerServices.IsConst) modopt([mscorlib]System.Runtime.CompilerServices.IsConst))
IL_0026: ret
} // end of method 'Global Functions'::.cctor
Comments
- Anonymous
November 21, 2005
cool - didn't know about that. Thanks for posting this.
Jonh - Anonymous
November 30, 2005
Yes, that's cool. Is there a way to add it in a C# assembly, other than by disassembling / inserting IL code / recompiling it? Maybe Microsoft should add an attribute that will make a static method the module initializer.