程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 瞎掰:C#類型構造器

瞎掰:C#類型構造器

編輯:C#入門知識

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

類型構造器,顧名思義,是一個類的類型的構造器(滿繞的)。它定義為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秒鐘。還是升級下硬件設備實在。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved