好吧 我是今天才知道有这家伙。

类型构造器,顾名思义,是一个类的类型的构造器(满绕的)。它定义为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秒钟。还是升级下硬件设备实在。

作者: 菜鸟老了 发表于 2011-07-20 10:56 原文链接

推荐.NET配套的通用数据层ORM框架:CYQ.Data 通用数据层框架