構造函數這個概念,在我們剛開始學習編程語言的時候,就被老師一遍一遍的教着。親,現在你還記得靜態構造函數的適用場景嗎?如果沒有,那么我們一起來復習一下吧。
靜態構造函數是在構造函數方法前面添加了static關鍵字之后形成的,並且沒有修飾符(public,private),沒有參數。
靜態構造函數有哪些特點呢:
- 靜態構造函數沒有修飾符修飾(public,private),因為靜態構造函數不是我們程序員調用的,是由.net 框架在合適的時機調用的。
- 靜態構造函數沒有參數,因為框架不可能知道我們需要在函數中添加什么參數,所以規定不能使用參數。
- 靜態構造函數前面必須是static 關鍵字。如果不加這個關鍵字,那就是普通的構造函數了。
- 靜態構造函數中不能實例化實例變量。(變量可以分為類級別和實例級別的變量,其中類級別的有static關鍵字修飾)。
- 靜態函數的調用時機,是在類被實例化或者靜態成員被調用的時候進行調用,並且是由.net框架來調用靜態構造函數來初始化靜態成員變量。
- 一個類中只能有一個靜態構造函數。
- 無參數的靜態構造函數和無參數的構造函數是可以並存的。因為他們一個屬於類級別,一個屬於實例級別,並不沖突。
- 靜態構造函數只會被執行一次。並且是在特點5中的調用時機中進行調用。
- 就像如果沒有在類中寫構造函數,那么框架會為我們生成一個構造函數,那么如果我們在類中定義了靜態變量,但是又沒有定義靜態構造函數,那么框架也會幫助我們來生成一個靜態構造函數來讓框架自身來調用。
上面幾個特點都是理論性的,我們來做一個找錯題,幫助我們一起來學習靜態構造函數。
1 public class C 2 { 3 public static string BB; 4 public static C() 5 { 6 BB = "CC"; 7 } 8 public static C(string mm) 9 { 10 BB = mm; 11 } 12 static C() 13 { 14 BB = "Right"; 15 } 16 public C() 17 { 18 BB = "Wrong"; 19 } 20 public C(string mm) 21 { 22 BB = mm; 23 } 24 }
VS編譯提示的錯誤信息:
現在我們來做一個有意思的事情,驗證靜態構造函數的調用時機:
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 6 Console.WriteLine(A.strText); 7 Console.WriteLine(B.strText); 8 Console.Read(); 9 } 10 } 11 public class A 12 { 13 public static string strText; 14 public string Text; 15 static A() 16 { 17 strText = "AAA"; 18 } 19 public A() 20 { 21 Text = "AAAAAAAAAAAAAAAAAAAAAAAAAA"; 22 } 23 } 24 public class B:A 25 { 26 static B() 27 { 28 strText = "BBB"; 29 } 30 public B() 31 { 32 Text = "BBBBBBBBBBBBBBBBB"; 33 } 34 }
輸出結果均為:AAA
我們來分析一下出現這個情況的原因所在,當顯示A.strText的時候,因為strText是靜態變量,所以框架會調用A的靜態構造函數,此時strText的值為AAA.正確
當顯示B.strText的時候,因為B繼承自A,所以會首先調用A的靜態構造函數,但是因為靜態構造函數只會調用一次,所以不會調用A的靜態構造函數,但是又因為strText屬於類A,而不是B,所以B得靜態構造函數不會執行,故輸出的均為AAA。
但是如果我們把輸出更改一下,輸出結果就大不一樣了。
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 B b = new B(); 6 A a = new A(); 7 8 Console.WriteLine(A.strText); 9 Console.WriteLine(B.strText); 10 11 Console.Read(); 12 } 13 } 14 public class A 15 { 16 public static string strText; 17 public string Text; 18 static A() 19 { 20 strText = "AAA"; 21 } 22 public A() 23 { 24 Text = "AAAAAAAAAAAAAAAAAAAAAAAAAA"; 25 } 26 } 27 public class B:A 28 { 29 static B() 30 { 31 strText = "BBB"; 32 } 33 public B() 34 { 35 Text = "BBBBBBBBBBBBBBBBB"; 36 } 37 }
請注意我在開始部分對類進行了實例化,那么此時的輸出結果就是均為BBB。
為什么會有這樣的情況出現呢,其實還是要從靜態構造函數的調用時機入手。
首先我們實例化了B,此時會調用B的靜態構造函數,但是因為strText是A的靜態變量,所以首先會先調用A的靜態構造函數將strText賦值為AAA,此時又會調用B的靜態構造函數將strText賦值為BBB,所以此時strText的值應該為BBB,所以輸出均為BBB。