Well, I only know this guy today.
The Type constructor, as its name implies, is a class Type constructor (full bypass ). It is defined as static and the access level can only be private.
The Type constructor is called before the class is accessed for the first time. It is used to initialize and assign values (if any) to static members inside the class. Non-static members inside the class are
Class constructor.
For example:
Public class SomeClass
{
Int32 I = 0; // initialize (. ctor) in the class constructor)
Static Int32 j = 0; // initialize (. cctor) in the Type constructor)
}
Method private hidebysig specialname rtspecialname static void. cctor () cel managed
{// Type constructor
. Maxstack 8
L_0000: ldc. i4.0 // encapsulate 4 into the computing Stack
L_0001: sts1_int32 CLR. SomeClass: j // Replace the position of j in the stack (since then, 4 has lived with j ?)
L_0006: ret
}
. Method public hidebysig specialname rtspecialname instance void. ctor () cel managed
{
. Maxstack 8
L_0000: ldarg.0
L_0001: ldc. i4.0
L_0002: st1_int32 CLR. SomeClass: I
L_0007: ldarg.0
Rochelle 0008: call instance void [mscorlib] System. Object:. ctor () // The constructor of the class calls the constructor of the base class.
L_000d: nop
L_000e: ret
}
In addition, we can obtain through decompilation. If the static variables in our class are not initialized, the corresponding Type constructor cannot be found in IL. That is
Public class SomeClass
{The corresponding. cctor () cannot be found in IL ().
Int32 static j;
}
For the default Type constructor, JIT will optimize it so that it can be called multiple times in the same method only once.
For the displayed Type constructor, JIT will embed it into the code of the method in the method called for the first time. That is, if the type is used n times in the method, the Type constructor of n times will be called.
Use an example to describe everything
(The following example is from "CLR via C #", pp. 174-175, translated by Zhou Jing, Tsinghua University Press, the third edition)
Using System;
Using System. Diagnostics;
Internal class BeforeFieldInit
{
Public static Int32 s_x = 123;
}
Class Precise
{
Public static Int32 s_x; // values are assigned to the wood. Therefore, the Type constructor is not checked during compilation.
Static Precise () {s_x = 123;} // Note: if this is found in wood, Precise does not generate a Type constructor during compilation.
}
Class Program ()
{
Const Int32 iterations = 2147483647;
PreTest1 (iterations );
PreTest2 (iterations );
Console. Read ();
}
Static void PreTest1 (Int32 iterations)
{
Stopwatch sw = Stopwatch. StartNew ();
For (Int32 x = 0; x <iterations; x ++)
{
BeforeFieldInit. s_x = 1;
}
Console. WriteLine ("P1: {0} BFI", sw. Elapsed );
Sw = Stopwatch. StartNew ();
For (Int32 x = 0; x <iterations; x ++)
{
Presise. s_x = 1;
}
Console. WriteLine ("P1: {0} Ps", sw. Elapsed );
}
Static void PreTest2 (Int32 iterations)
{
Stopwatch sw = Stopwatch. StartNew ();
For (Int32 x = 0; x <iterations; x ++)
{
BeforeFieldInit. s_x = 1;
}
Console. WriteLine ("P1: {0} BFI", sw. Elapsed );
Sw = Stopwatch. StartNew ();
For (Int32 x = 0; x <iterations; x ++)
{
Presise. s_x = 1;
}
Console. WriteLine ("P1: {0} Ps", sw. Elapsed );
}
}
}
Multiple output results are similar:
The running result after commenting on the Precise Type constructor is as follows:
In conclusion, a 2 ^ 32 cycle saves about 4 seconds. Or upgrade the hardware.