先看一道常見題目,如下代碼的執行結果是什麼?安全
class A { public static int X = B.Y + 1; static void Main(string[] args) { Console.WriteLine(X); } } class B { public static int Z = 10; public static int Y; static B() { Console.WriteLine(Z); Y = A.X + 1; } }
1、定義多線程
由名稱可知,靜態構造函數(也稱爲類型構造函數)包含「靜態」和「構造函數」兩個特色。第一個特色決定了它與靜態函數相似,只能使用靜態成員;第二個特色決定了它與構造函數相似,具備初始化做用,而且沒有返回值。函數
與構造函數(針對實例對象)不一樣的是,靜態構造函數(針對類)只執行一次,而且是在第一個實例對象建立前被調用,因此它能夠用於那些只須要執行一次的操做;並且它不容許有public等修飾符,由程序自動調用,不能被外界調用。spa
總結:靜態構造函數用於初始化任何靜態數據,或者用於執行僅需執行一次的操做;在建立第一個實例對象或者引用任何靜態變量以前,將自動調用靜態構造函數。線程
特色:對象
一、靜態構造函數既沒有訪問修飾符,也沒有參數。blog
二、在建立第一個實例或引用任何靜態成員以前,將自動調用靜態構造函數來初始化類。同步
三、沒法直接調用靜態構造函數。 string
四、在程序中,用戶沒法控制什麼時候執行靜態構造函數。it
五、線程安全。
關於線程安全須要特別說明一下,因爲程序可能在多線程環境下運行,也就是可能出現同時多個線程準備執行靜態構造函數的狀況。CLR確保這個過程是安全的,實際上調用靜態構造函數的線程須要先得到一個互斥線程同步鎖,若是有多個線程試圖執行類型的靜態構造函數,只有一個線程能得到該鎖;得到鎖的線程完成初始類型初始化操做,其它線程只能等待;當初始化完成,等待的線程被喚醒,而後發現靜態構造函數已經被執行過,就不會再執行。
2、語法
public class StaticTester { static StaticTester() { } }
3、做用
用於初始化靜態成員。有時候咱們會從配置文件讀取一些值做爲靜態變量,相似這樣:
public class StaticTester { private static readonly string key = ConfigurationManager.AppSettings["key"]; private static readonly string value = ConfigurationManager.AppSettings["value"]; static StaticTester() { } }
若是要讀取的配置信息比較多,並且要加入一些邏輯判斷,那麼能夠這樣:
public class StaticTester { private static readonly string key; private static readonly string value; static StaticTester() { key = ConfigurationManager.AppSettings["key"]; if (string.IsNullOrEmpty(key)) { throw new Exception("key變量未被正確配置!"); } value = ConfigurationManager.AppSettings["value"]; if (string.IsNullOrEmpty(value)) { throw new Exception("value變量未被正確配置!"); } } }
4、執行順序
1. 運行時,優先對靜態變量進行初始化。
2. 若是有靜態構造函數,那麼在建立第一個實例對象或者引用任何靜態變量以前,調用靜態構造函數。
3. 其它操做。