C# 建構函式總結
建構函式
建構函式分為:例項建構函式,靜態建構函式,私有建構函式。
例項建構函式
1、建構函式的名字與類名相同。
2、使用 new 表示式建立類的物件或者結構(例如int)時,會呼叫其建構函式。並且通常初始化新物件的資料成員。
3、除非類是靜態的,否則會為沒有建構函式的類,自動生成一個預設建構函式,並使用預設值來初始化物件欄位。
4、建構函式可以有引數,可以以多型的形式存在多個建構函式。
例:
class CoOrds { public int x, y; // 例項建構函式(預設建構函式) public CoOrds() { x = 0; y = 0; } // 具有兩個引數的建構函式 public CoOrds(int x, int y) { this.x = x; this.y = y; } // 重寫toString方法 public override string ToString() { return (String.Format("({0},{1})", x, y)); } static void Main(string[] args) { CoOrds p1 = new CoOrds(); CoOrds p2 = new CoOrds(5, 3); // 使用重寫ToString方法顯示結果 Console.WriteLine("CoOrds #1 at {0}", p1); Console.WriteLine("CoOrds #2 at {0}", p2); Console.ReadKey(); } } /* Output: CoOrds #1 at (0,0) CoOrds #2 at (5,3) */
其中CoOrds()是建構函式,諸如此類不帶引數的建構函式稱為“預設建構函式”。
CoOrds(int x, int y)同樣也是建構函式,建構函式可以有引數,允許多型。
靜態建構函式
靜態建構函式具有以下屬性:
-
靜態建構函式不使用訪問修飾符或不具有引數。
-
在建立第一個例項或引用任何靜態成員之前,將自動呼叫靜態建構函式以初始化類。
-
不能直接呼叫靜態建構函式。
-
使用者無法控制在程式中執行靜態建構函式的時間。
-
靜態建構函式的一種典型用法是在類使用日誌檔案且將建構函式用於將條目寫入到此檔案中時使用。
-
靜態建構函式對於建立非託管程式碼的包裝類也非常有用,這種情況下建構函式可呼叫
LoadLibrary
-
如果靜態建構函式引發異常,執行時將不會再次呼叫該函式,並且型別在程式執行所在的應用程式域的生存期內將保持未初始化。
建構函式與靜態建構函式:
class TestClass { public static int x = 0; //建構函式 TestClass() { x = 1; } //靜態建構函式 static TestClass() { //第二步,執行x = 2 x = 2; } //第一步,程式入口Main最先執行。然後執行public static int x = 0 接著執行靜態建構函式。 public static void Main(string[] args) { Console.WriteLine("x:{0}", x); //列印,x = 2 TestClass Test = new TestClass();//第三步執行建構函式,此時x = 1 Console.WriteLine("x:{0}", x); //列印 x = 1 Console.Read(); } }
Main是程式入口,當執行Main的時候,最先執行public static int x = 0
接著執行靜態建構函式,此時 x = 2
然後執行Main函式裡面的內容,列印 x,此時 x = 2
初始化TestClass,然後會執行建構函式,此時 x = 1
列印 x = 1
那麼,在呼叫某類的靜態函式時真正的執行順序:
1、靜態變數 > 靜態建構函式 > 靜態函式
2、靜態變數 > 靜態建構函式 > 建構函式
C#高效程式設計改進C#程式碼的50個行之有效的辦法(第2版)裡說到這樣一段話:
型別例項的完整過程。你需要理解這些操作的順序,以及物件的預設初始化操作。你要保證在構造的過程中對每個成員變數僅初始化一次。實現這一點最好的方法就是,儘可能的早地進行初始化。
下面就是建立某個型別的第一個例項時,所進行的操作順序為:
(1)靜態變數設定為0
(2)執行靜態變數初始化器
(3)執行基類的靜態建構函式
(4)執行靜態建構函式
(5)例項變數設定為0
(6)執行衯變數初始化器
(7)執行基類中合適的例項建構函式
(8)執行例項建構函式同樣型別的第二個以及以後的例項將從第5步開始執行,因為類的構造器僅會執行一次。此外,第6步和第7步將被優化,以便建構函式初始化器使編譯器移除重複的指令。
練習題:
public class A { public static readonly int x; static A() { x = B.y + 1; } } public class B { public static int y = A.x + 1; public static void Main(string[] args) { Console.WriteLine("x:{0},y:{1}。", A.x, y); Console.ReadLine(); } }
下面公佈答案:
練習題答案
詳細解答:
1、首先,每一個專案有且只能有一個靜態類的Main函式作為入口函式。而入口函式是最先執行的。
2、由於Main函式在B類裡面,首先會初始化B類。而類的初始化順序是:類裡的靜態變數,然後執行靜態建構函式。
3、執行起先執行 public static int y = A.x + 1 這個,執行的時候,會先把 y 初始化為0,然後計算 y 的值。
4、計算 y 的值的時候,呼叫了 A 的靜態變數 x 。所以會先初始化A。
5、初始化A時首先去執行 public static readonly int x ,先把 x 初始化為0。
6、然後執行A的靜態建構函式 x = B.y + 1 此時 y 已經初始化為0了。
7、計算得到 x = 1。然後回到 public static int y = A.x + 1 得到 y = 2。
8、然後再執行Main函式的內容。得出結果x=1,y=2
私有建構函式
私有建構函式是一種特殊的例項建構函式。 它通常用於只包含靜態成員的類中。 如果類具有一個或多個私有建構函式而沒有公共建構函式,則其他類(除巢狀類外)無法建立該類的例項。
public class PrivateConstructor { private PrivateConstructor() { //PrivateTest a = new PrivateTest(); //註釋開啟會報錯,錯誤資訊:不可訪問,因為它受保護級別限制。因為私有建構函式無法在類的外面例項化。 } public class PrivateTest { int i; private PrivateTest() { i = 3; } static void Main(string[] args) { PrivateConstructor t = new PrivateConstructor(); //巢狀類允許例項化。 PrivateTest p = new PrivateTest(); //類的內部允許例項化。 Console.WriteLine("i:{0}", p.i); //結果:i:3 Console.Read(); } } }
宣告空建構函式可阻止自動生成預設建構函式。 請注意,如果不對建構函式使用訪問修飾符,則在預設情況下它仍為私有建構函式。 但是,通常會顯式地使用 private 修飾符來清楚地表明該類不能被例項化。
例項:
其中單例模式就用到了私有建構函式的特性來保證類不會被例項化。C# 單例模式