記得我在分析readonly關鍵字那篇文字裡,我用到了類型構造器。後來想了想,我能不能不用類型構造器呢?左想右想,還是不行,非得用它不可,因為字段是readonly修飾,且他娘的還是static的,地球人都知道,我絕不能拿對象構造器去初始化一個static修飾的字段。
我查了查CLR規范,發現類型構造器非常棘手,不好用,甚至值類型不能定義類型構造器。
廢話少說,來看DEMO。
先定義個帶類型構造器的值類型。
namespace static類型構造器
{
struct StataicBuilderValueType
{
static StataicBuilderValueType()//never do here
{
Console.WriteLine("hai......");
Console.ReadLine();
}
}
}
再在主類中構造十個StataicBuilderValueType類型的對象,看DEMO。
namespace static類型構造器
{
class Program
{
static void
{
StataicBuilderValueType[] sv=new StataicBuilderValueType[10];
}
}
}
我在類型構造器中設置一個斷點,然後跟蹤,發現程序在斷點處根本就不停,嘩,全過去了。我做了N次。
所以切記,不要在結構,值類型中,使用類型構造初試化值,它會讓你失望的。
再看看CLR對類型構造器的其他約束。
在CLR規范中這樣寫道;“CLR保證每個應用程序域的類型構造器只執行一次,而且線程是安全的”,這是原話。
解釋一下,在CLR規范中,應用程序域的定義,她是程序進程的邏輯叫法.
所謂,線程安全,就是資源在同一時間點,只有一個線程能訪問,其他線程要訪問,必須等上一個線程,釋放她的線程同步鎖。
來看DEMO
定義帶類型構造器的引用類型
namespace static類型構造器
{
class Test2
{
&
nbsp; static int i = 0;
static Test2()
{
i = i+1;
Console.WriteLine("hai......");
}
public static Int32 getValue()
{
return i;
}
}
}
再定義帶MAIN方法的主類
namespace static類型構造器
{
class Program
{
static void
{
int i = Test2.getValue();
Console.WriteLine(i);
System.Threading.Thread thread = new System.Threading.Thread(new System.Threading.ThreadStart(ThreadProc));
thread.Start();
Console.ReadLine();
}
public static void ThreadProc()
{
int n=Test2.getValue();
Console.WriteLine(n);
}
}
}
在Main方法中首先調用類型構造器,因為執行了Test2.getValue(),對類型進行了引用,當然會執行類型構造器了。然後,在主線程中開辟一新的線程thread,在線程thread中也執行Test2.getValue()方法。
那麼在thread中會不會對引用類型的構造器進行調用呢?
來看輸出
可以看到當主線程調用類型構造器,並釋放線程同步鎖後,線程thread,雖然顯示的去調用類型構造器,但是底層CLR根本沒執行,I還是等於1。這是因為CLR會去檢查是否已經執行了類型構造器,如果執行了,CLR永遠不再生成調用類型構造器的本地代碼。
備注;ctor與cctor的區別