詳解c# 類的構(gòu)造方法
一、構(gòu)造方法
類的構(gòu)造方法是類的成員方法的一種,它的作用是對類中的成員進行初始化操作。類的構(gòu)造方法分為:
1.靜態(tài)構(gòu)造方法
2.實例構(gòu)造方法
1.靜態(tài)構(gòu)造方法
類的靜態(tài)構(gòu)造方法是類的成員方法的一種,它的作用是對類中的靜態(tài)成員進行初始化操作。下面請看代碼實例:
using System; namespace LycheeTest { class Test { //定義一個靜態(tài)成員變量 private static int a; //定義靜態(tài)構(gòu)造函數(shù) static Test() { //初始化靜態(tài)成員變量 a = 11; } public void Show() { Console.WriteLine("靜態(tài)字段 a 的值是:{0}", a); } } class Program { static void Main(string[] args) { Test t = new Test(); t.Show(); Console.ReadKey(); } } }
首先,上面這段代碼定義了兩個類。第 3 行代碼定義了類 Test。定義類的時候,類的訪問權(quán)限修飾符有兩個,一個是 public,另一個是 internal。當(dāng)不寫任何訪問修飾符的時候,類的訪問權(quán)限默認是 internal。 這個訪問權(quán)限的意義是,這個類只能被本程序集訪問,不能被本程序集以外的類訪問。如果這個類是屬于類庫的,那么它必須是 public 的,否則調(diào)用它的程序集就不能訪問它。第 5 行代碼定義了一個靜態(tài)字段成員,第 7 行代碼就是靜態(tài)構(gòu)造方法??梢钥吹?,靜態(tài)構(gòu)造方法的特點是,以 static 關(guān)鍵字說明這個方法是靜態(tài)的,方法名稱要和類名完全相同,這里要注意大小寫。靜態(tài)構(gòu)造方法不能含有參數(shù),靜態(tài)構(gòu)造方法不能有返回值。在靜態(tài)構(gòu)造方法體內(nèi)可以做初始化靜態(tài)成員的操作。第 11 行代碼定義了一個實例方法,它的作用是輸出靜態(tài)字段的值。在第 16 行的類 Program 中的 Main(注意:在java中是main) 方法中調(diào)用了這個類,第 18行創(chuàng)建了這個類的一個實例,第 19 行 調(diào)用了類的實例方法。
從上面的代碼中可以看到,并沒有顯式調(diào)用類的靜態(tài)構(gòu)造方法。
下面請看以上代碼的執(zhí)行結(jié)果:
靜態(tài)字段 a 的值是:11
可以看到,靜態(tài)構(gòu)造方法確實是被執(zhí)行了。那么上例就是靜態(tài)構(gòu)造方法的執(zhí)行條件之一,在類的實例被創(chuàng)建時,類的靜態(tài)構(gòu)造方法將被自動調(diào)用。
靜態(tài)構(gòu)造方法的調(diào)用次序是在靜態(tài)字段的初始值設(shè)定項之后。
也就是第一步是靜態(tài)字段的默認值設(shè)置,第二步是執(zhí)行靜態(tài)字段的初始值設(shè)定項,第三步就是調(diào)用類的靜態(tài)構(gòu)造方法。
下面將前面的代碼實例修改一下,代碼如下:
using System; namespace LycheeTest{ class Test { private static int a; static Test() { a++; } public void Show() { Console.WriteLine("靜態(tài)字段 a 的值是:{0}", a); 14 } } class Program { static void Main(string[] args) { Test t = new Test(); t.Show(); Test t1 = new Test(); t.Show(); Console.ReadKey(); } } }
這段代碼將靜態(tài)構(gòu)造方法做了修改,在方法體內(nèi)將靜態(tài)字段 a 進行自增操作。然后在代碼的第 17 行又 創(chuàng)建了一個類的實例,然后再次調(diào)用類的實例方法。
下面看執(zhí)行結(jié)果:
靜態(tài)字段 a 的值是:1 靜態(tài)字段 a 的值是:1
可以看到,靜態(tài)字段的值并沒有增加。這就是靜態(tài)構(gòu)造方法執(zhí)行的特點,它只執(zhí)行了一次。當(dāng)程序集 運行的時候,將會創(chuàng)建一個應(yīng)用程序域,在一個應(yīng)用程序域中,類的靜態(tài)構(gòu)造方法僅僅執(zhí)行一次。
下面再對代碼實例進行修改如下:
using System; namespace LycheeTest { class Test { public static int a; static Test() { Console.WriteLine("類的靜態(tài)構(gòu)造方法開始執(zhí)行"); a++; } public void Show() { Console.WriteLine("靜態(tài)字段 a 的值是:{0}", a); } } class Program { static void Main(string[] args) { Console.WriteLine("靜態(tài)字段 a 的值是:{0}", Test.a); Console.WriteLine("靜態(tài)字段 a 的值是:{0}", Test.a); Console.ReadKey(); } } }
這段代碼在類的靜態(tài)構(gòu)造方法中打印輸出了一行標記,類的靜態(tài)字段的訪問權(quán)限也修改為 public,這讓它可以在類外被調(diào)用。在 Main 方法中兩次打印輸出了靜態(tài)字段的值,注意在類外調(diào)用類的靜態(tài)字段需要 使用類名進行引用。
下面是代碼的執(zhí)行結(jié)果:
類的靜態(tài)構(gòu)造方法開始執(zhí)行 靜態(tài)字段 a 的值是:1 靜態(tài)字段 a 的值是:1
本段代碼并沒有創(chuàng)建類的實例。在引用類的靜態(tài)成員之前,類的靜態(tài)構(gòu)造方法將被調(diào)用。這個被調(diào)用的類的靜態(tài)成員包括靜態(tài)字段和靜態(tài)方法。這就是類的靜態(tài)構(gòu)造方法調(diào)用的第二個條件。
下面再對代碼實例進行修改如下:
using System; namespace LycheeTest { class Program { private static int a; static Program() { Console.WriteLine("類的靜態(tài)構(gòu)造方法被調(diào)用"); a = 11; } static void Main(string[] args) { Console.WriteLine("Main 方法被調(diào)用"); Console.WriteLine("靜態(tài)字段 a 的值是:{0}", a); Console.ReadKey(); } } }
這段代碼在包含 Main 方法的類中定義了靜態(tài)字段和靜態(tài)構(gòu)造方法。因為 Main 方法也是一個靜態(tài)方法,類的靜態(tài)構(gòu)造方法被調(diào)用而且它是類的入口點方法,那么它和類的靜態(tài)構(gòu)造方法之間是誰先調(diào)用呢?下面首先來看代碼的執(zhí)行結(jié)果:
類的靜態(tài)構(gòu)造方法被調(diào)用 Main 方法被調(diào)用 靜態(tài)字段 a 的值是:11
通過代碼的執(zhí)行結(jié)果可以看到,因為類的入口點方法仍然是一個靜態(tài)方法,那么在任何靜態(tài)成員被調(diào)用之 前,靜態(tài)構(gòu)造方法都首先被調(diào)用。所以,可以得出如下結(jié)論,類的靜態(tài)構(gòu)造方法先于類的 Main 方法被調(diào)用。
那么類的靜態(tài)構(gòu)造方法能否被顯式調(diào)用呢?下面看代碼實例:
using System; namespace LycheeTest { class Program { private static int a; static Program() { Console.WriteLine("類的靜態(tài)構(gòu)造方法被調(diào)用"); a = 11; } static void Main(string[] args) { Program(); Console.ReadKey(); } } }
在這段代碼中的第 10 行顯式調(diào)用了類的靜態(tài)構(gòu)造方法,這時編譯器會報錯。
2.實例構(gòu)造函數(shù)
類的實例構(gòu)造方法是類的成員方法的一種,它的作用是對類的實例成員進行初始化操作。實例構(gòu)造方法可以實現(xiàn)重載,在創(chuàng)建類的實例時,可以顯式的指定不同的參數(shù)來調(diào)用重載的不同的實例構(gòu)造方法。下面請看代碼實例:
using System; namespace LycheeTest { class Program { private static int a; private int b = 12; private string c = "Hello World"; static Program() { Console.WriteLine("類的靜態(tài)構(gòu)造方法被調(diào)用"); a = 11; } public Program(int a, string s) { Console.WriteLine("帶二個參數(shù)的構(gòu)造方法被調(diào)用"); this.b = a; this.c = s; } public Program(int a) : this(a, "通過 this 關(guān)鍵字調(diào)用構(gòu)造方法") { Console.WriteLine("帶一個參數(shù)的構(gòu)造方法被調(diào)用"); } public void Show() { Console.WriteLine("靜態(tài)字段 a 的值是:{0}", a); Console.WriteLine("實例字段 b 的值是:{0}", b); Console.WriteLine("實例字段 c 的值是:{0}", c); } static void Main(string[] args) { Program p1 = new Program(33, "這是創(chuàng)建的實例 P1"); Program p2 = new Program(34); p1.Show(); p2.Show(); Console.ReadKey(); } }
這段代碼的第 4 行、第 5 行和第 6 行分別定義了三個字段成員,第 4 行是靜態(tài)字段,第 5 行和第 6 行代碼都有初始值設(shè)定項。代碼的第 8 行就是一個實例構(gòu)造方法的定義,實例構(gòu)造方法也是以類名作為方法名,它沒有返回值, 在方法名前面是訪問權(quán)限修飾符,可以使用的訪問權(quán)限修飾符包括 public、private 和 protected。其中的 protected 意味著構(gòu)造方法只能在此類內(nèi)部訪問。實例構(gòu)造方法可以帶參數(shù)。 第 12 行代碼的實例構(gòu)造方法使用兩個傳入的參數(shù)對實例字段進行了賦值。第 17 行代碼定義了帶一個參數(shù)的實例構(gòu)造方法,它和前一個實例構(gòu)造方法形成了重載。實例構(gòu)造方法可以通過 this 關(guān)鍵字調(diào)用其他的實例構(gòu)造方法,方法就是在參數(shù)列表的后面使用冒號然后接 this 關(guān)鍵字, 然后再跟參數(shù)列表,這個參數(shù)列表要匹配另一個重載的實例構(gòu)造方法。第 17 行的構(gòu)造方法只有一個參數(shù), 它將這個參數(shù)通過 this 關(guān)鍵字傳遞給了另一個構(gòu)造方法,在用 this 調(diào)用另一個構(gòu)造方法的時候,為其同時傳入了一個字符串參數(shù)。第 24 行的實例方法打印類的字段成員的值。在 Main 方法中,第 26 行代碼和第 27 行代碼分別定義了兩個實例,它們使用 new 關(guān)鍵字調(diào)用了不同的實例構(gòu)造方法。第 28 行和第 29 行分別調(diào)用實例方法打印類的靜態(tài)字段和實例的兩個字段成員的值。
下面先來看代碼的執(zhí)行結(jié)果:
類的靜態(tài)構(gòu)造方法被調(diào)用 帶二個參數(shù)的構(gòu)造方法被調(diào)用 帶二個參數(shù)的構(gòu)造方法被調(diào)用 帶一個參數(shù)的構(gòu)造方法被調(diào)用 靜態(tài)字段 a 的值是:11 實例字段 b 的值是:33 實例字段 c 的值是:這是創(chuàng)建的實例 P1 靜態(tài)字段 a 的值是:11 實例字段 b 的值是:34 實例字段 c 的值是:通過 this 關(guān)鍵字調(diào)用構(gòu)造方法
現(xiàn)在用執(zhí)行結(jié)果來介紹實例構(gòu)造方法的執(zhí)行過程,當(dāng)?shù)?26 行代碼創(chuàng)建類的實例時,類的靜態(tài)字段首先被設(shè)置成默認值,因為沒有字段的初始值設(shè)定項,所以接著就執(zhí)行類的靜態(tài)構(gòu)造方法。這時靜態(tài)字段 a 被 設(shè)置成 11。因為第 26 行代碼使用 new 調(diào)用了帶有兩個參數(shù)的實例構(gòu)造方法,所以首先實例字段 b 被設(shè)置為 0,實例字段 c 被設(shè)置為 null。然后執(zhí)行字段的初始值設(shè)定項,b 被賦值為 12,c 被賦值為“Hello World”。接 下來執(zhí)行實例構(gòu)造方法體中的第一個語句,“帶二個參數(shù)的構(gòu)造方法被調(diào)用”這個字符串被打印。接下來 實例 p1 的字段 b 被設(shè)置為傳入的參數(shù) 33,注意構(gòu)造方法的形參 a 在這里覆蓋了類的靜態(tài)字段 a。也就是說, 這時起作用的是實例構(gòu)造方法的局部變量 a。然后實例字段 c 被設(shè)置為字符串"這是創(chuàng)建的實例 P1"。第 27 行代碼使用 new 關(guān)鍵字調(diào)用了帶一個參數(shù)的實例構(gòu)造方法,在調(diào)用時,首先屬于 p2 的實例字段 b 被設(shè)置為 0,實例字段 c 被設(shè)置為 null。然后執(zhí)行字段的初始值設(shè)定項,b 被賦值為 12,c 被賦值為“Hello World”。接下來執(zhí)行的是 this 引用的帶兩個參數(shù)的實例構(gòu)造方法,"帶二個參數(shù)的構(gòu)造方法被調(diào)用"這個 字符串被打印。然后 b 被設(shè)置為 34,c 被設(shè)置為"通過 this 關(guān)鍵字調(diào)用構(gòu)造方法"。最后,代碼控制又返回 來執(zhí)行帶一個參數(shù)的實例構(gòu)造方法體中的打印語句,"帶一個參數(shù)的構(gòu)造方法被調(diào)用"這個字符串被打印。 至此,實例構(gòu)造方法的執(zhí)行完畢。接下來的代碼打印靜態(tài)字段的值,可以看到兩個實例打印出來的靜態(tài)字段值是一樣的,但是它們的實 例字段的值各不相同。
可選參數(shù)和命名參數(shù)也可以用于實例構(gòu)造方法,下面看代碼實例:
using System; namespace LycheeTest { class Program { private int b; private string c; public Program(int a = 12, string s = "") { this.b = a; this.c = s; } public void Show() { Console.WriteLine("實例字段 b 的值是:{0}", b); Console.WriteLine("實例字段 c 的值是:{0}", c); } static void Main(string[] args) { Program p1 = new Program(); //構(gòu)造方法的兩個參數(shù)都采用默認值 Program p2 = new Program(34); //構(gòu)造方法的 string 類型參數(shù)采用默認值 Program p3 = new Program(23, "Hello World"); //構(gòu)造方法的兩個參數(shù)采用傳入?yún)?shù) Program p4 = new Program(s: "今天的天氣真好"); //采用命名參數(shù),另一個參數(shù) a 采用默認值 p1.Show(); p2.Show(); p3.Show(); p4.Show(); Console.ReadKey(); } } }
代碼的第 6 行定義了一個帶有可選參數(shù)和命名參數(shù)的構(gòu)造方法,然后第 15 創(chuàng)建了一個類的實例,在構(gòu)造方法中沒有傳入任何參數(shù),這時,構(gòu)造方法的兩個參數(shù)都采用默認值。第 16 行代碼為構(gòu)造方法傳入了一個 int 類型的參數(shù),這時,另一個 string 類型的參數(shù)采用默認值。 第 17 行代碼傳入了兩個參數(shù),構(gòu)造方法的兩個參數(shù)都使用了這兩個傳入的參數(shù)。第 18 行代碼使用了命名參數(shù)指定傳入的參數(shù)是 string 類型的參數(shù),并將它傳遞給形參 s。這時另一 個 int 類型的參數(shù)采用默認值。第 19 行到第 23 行代碼打印類的實例字段的值。這段代碼的執(zhí)行結(jié)果如下:
實例字段 b 的值是:12 實例字段 c 的值是: 實例字段 b 的值是:34 實例字段 c 的值是: 實例字段 b 的值是:23 實例字段 c 的值是:Hello World 實例字段 b 的值是:12 實例字段 c 的值是:今天的天氣真好
以上就是本文的全部內(nèi)容,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作能帶來一定的幫助,同時也希望多多支持腳本之家!