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