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) */
分析:
1.其中CoOrds()是構造函數,諸如此類不帶參數的構造函數稱為“默認構造函數”。
2.CoOrds(int x, int y)同樣也是構造函數,構造函數可以有參數,允許多態。
三、靜態構造函數
1.靜態構造函數不使用訪問修飾符或不具有參數。
2.在創建第一個實例或引用任何靜態成員之前,將自動調用靜態構造函數以初始化類。
3.不能直接調用靜態構造函數。
4.用戶無法控制在程序中執行靜態構造函數的時間。
5.靜態構造函數的一種典型用法是在類使用日志文件且將構造函數用於將條目寫入到此文件中時使用。
6.靜態構造函數對於創建非托管代碼的包裝類也非常有用,這種情況下構造函數可調用 LoadLibrary 方法。
7.如果靜態構造函數引發異常,運行時將不會再次調用該函數,並且類型在程序運行所在的應用程序域的生存期內將保持未初始化。
代碼1:
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(); } }
分析1:
1.Main是程序入口,當執行Main的時候,最先執行public static int x = 0
2.接着執行靜態構造函數,此時 x = 2
3.然后執行Main函數里面的內容,打印 x,此時 x = 2
4.初始化TestClass,然后會執行構造函數,此時 x = 1
5.打印 x = 1
代碼2:
public class A { public static readonly int x; static A() { //第二步,調用B.y,此處B.y = 0,因為int類型在初始化階段,會給賦默認值,默認值為0。最后x = 0 + 1(返回給第一步) x = B.y + 1; } } public class B { //第一步,調用A.x,然后執行類A的靜態構造函數,等待返回(第二步返回的A.x = 1,所以y = 1 + 1) public static int y = A.x + 1; public static void Main(string[] args) { //第三步,A.x = 1,y = 2。 Console.WriteLine("x:{0},y:{1}。", A.x, y); Console.ReadLine(); } }
分析2:
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 修飾符來清楚地表明該類不能被實例化。