好吧 我是今天才知道有這家伙。
類型構造器,顧名思義,是一個類的類型的構造器(滿繞的)。它定義為static並且訪問級別只能是private。
類型構造器在類被第一次訪問前調用,用來對類內部的靜態成員進行初始化賦值(如果有的話),類內部的非靜態成員在
類的構造器裡面進行初始化。
例如:
public class SomeClass
{
Int32 i=0;//在類的構造器中進行初始化(.ctor)
static Int32 j=0;//在類型構造器中進行初始化(.cctor)
}
method private hidebysig specialname rtspecialname static void .cctor() cil managed
{//類型構造器
.maxstack 8
L_0000: ldc.i4.0 //將4封裝入計算堆棧
L_0001: stsfld int32 CLR.SomeClass::j//替換j在棧中位置(從此以後4和j同居了?)
L_0006: ret
}
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed
{
.maxstack 8
L_0000: ldarg.0
L_0001: ldc.i4.0
L_0002: stfld int32 CLR.SomeClass::i
L_0007: ldarg.0
L_0008: call instance void [mscorlib]System.Object::.ctor()//類的構造函數中會調用基類的構造函數。
L_000d: nop
L_000e: ret
}
並且,我們可以通過反編譯得到,如果我們類中的靜態變量沒有進行初始化,那麼在IL裡面找不到相應的類型構造器。即
public class SomeClass
{在IL裡面 找不到相應的.cctor()。
Int32 static j;
}
對於默認的類型構造器,JIT會進行優化,使它即時在同一個方法裡多次調用也只需執行一次。
對於顯示的類型構造器,JIT會在第一次調用它的方法裡將它嵌入到方法的代碼裡。即如果在方法裡用到了n次這個類型,那麼就會調用n次的類型構造器。
用例子說明一切吧
(下面的例子來自"CLR via C#"第三版 清華大學出版社 周靖 譯 第174-175頁)
using System;
using System.Diagnostics;
internal class BeforeFieldInit
{
public static Int32 s_x=123;
}
class Precise
{
public static Int32 s_x;//木有賦值,所以編譯的時候不檢測是否有類型構造器。
static Precise(){s_x=123;}//注:如果木有這個東西,編譯的時候Precise不會生成類型構造器
}
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);
}
}
}
多次輸出結果的都差不多:
把Precise的類型構造器注釋後的運行結果如下:
最後,總結一句話,2^32次循環才節約大概4秒鐘。還是升級下硬件設備實在。