先看一道常見題目,以下代碼的執行結果是什麼? 一、定義 由名稱可知,靜態構造函數(也稱為類型構造函數)包含“靜態”和“構造函數”兩個特點。第一個特點決定了它與靜態函數類似,只能使用靜態成員;第二個特點決定了它與構造函數類似,具有初始化作用,並且沒有返回值。 與構造函數(針對實例對象)不同的是,靜態構 ...
先看一道常見題目,以下代碼的執行結果是什麼?
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; } }
一、定義
由名稱可知,靜態構造函數(也稱為類型構造函數)包含“靜態”和“構造函數”兩個特點。第一個特點決定了它與靜態函數類似,只能使用靜態成員;第二個特點決定了它與構造函數類似,具有初始化作用,並且沒有返回值。
與構造函數(針對實例對象)不同的是,靜態構造函數(針對類)只執行一次,並且是在第一個實例對象創建前被調用,所以它可以用於那些只需要執行一次的操作;而且它不允許有public等修飾符,由程式自動調用,不能被外界調用。
總結:靜態構造函數用於初始化任何靜態數據,或者用於執行僅需執行一次的操作;在創建第一個實例對象或者引用任何靜態變數之前,將自動調用靜態構造函數。
特點:
1、靜態構造函數既沒有訪問修飾符,也沒有參數。
2、在創建第一個實例或引用任何靜態成員之前,將自動調用靜態構造函數來初始化類。
3、無法直接調用靜態構造函數。
4、在程式中,用戶無法控制何時執行靜態構造函數。
5、線程安全。
關於線程安全需要特別說明一下,由於程式可能在多線程環境下運行,也就是可能出現同時多個線程準備執行靜態構造函數的情況。CLR確保這個過程是安全的,實際上調用靜態構造函數的線程需要先獲得一個互斥線程同步鎖,如果有多個線程試圖執行類型的靜態構造函數,只有一個線程能獲得該鎖;獲得鎖的線程完成初始類型初始化操作,其它線程只能等待;當初始化完成,等待的線程被喚醒,然後發現靜態構造函數已經被執行過,就不會再執行。
二、語法
public class StaticTester { static StaticTester() { } }
三、作用
用於初始化靜態成員。有時候我們會從配置文件讀取一些值作為靜態變數,類似這樣:
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變數未被正確配置!"); } } }
四、執行順序
1. 運行時,優先對靜態變數進行初始化。
2. 如果有靜態構造函數,那麼在創建第一個實例對象或者引用任何靜態變數之前,調用靜態構造函數。
3. 其它操作。