詳解C#編程中構(gòu)造函數(shù)的使用
當(dāng)類(lèi)或結(jié)構(gòu)創(chuàng)建時(shí),其構(gòu)造函數(shù)調(diào)用。構(gòu)造函數(shù)與選件類(lèi)或結(jié)構(gòu)相同,并且,它們通常用于初始化新對(duì)象的數(shù)據(jù)成員。
在下面的示例中,使用一個(gè)簡(jiǎn)單的構(gòu)造函數(shù)定義了名為 Taxi 的類(lèi)。然后使用 new 運(yùn)算符來(lái)實(shí)例化該類(lèi)。在為新對(duì)象分配內(nèi)存之后,new 運(yùn)算符立即調(diào)用 Taxi 構(gòu)造函數(shù)。
public class Taxi { public bool isInitialized; public Taxi() { isInitialized = true; } } class TestTaxi { static void Main() { Taxi t = new Taxi(); Console.WriteLine(t.isInitialized); } }
不帶參數(shù)的構(gòu)造函數(shù)稱(chēng)為“默認(rèn)構(gòu)造函數(shù)”。無(wú)論何時(shí),只要使用 new 運(yùn)算符實(shí)例化對(duì)象,并且不為 new 提供任何參數(shù),就會(huì)調(diào)用默認(rèn)構(gòu)造函數(shù)。
除非類(lèi)是 static 的,否則 C# 編譯器將為無(wú)構(gòu)造函數(shù)的類(lèi)提供一個(gè)公共的默認(rèn)構(gòu)造函數(shù),以便該類(lèi)可以實(shí)例化。
通過(guò)將構(gòu)造函數(shù)設(shè)置為私有構(gòu)造函數(shù),可以阻止類(lèi)被實(shí)例化,如下所示:
class NLog { // Private Constructor: private NLog() { } public static double e = Math.E; //2.71828... }
結(jié)構(gòu)類(lèi)型的構(gòu)造函數(shù)與類(lèi)的構(gòu)造函數(shù)類(lèi)似,但是 structs 不能包含顯式默認(rèn)構(gòu)造函數(shù),因?yàn)榫幾g器將自動(dòng)提供一個(gè)構(gòu)造函數(shù)。此構(gòu)造函數(shù)會(huì)將 struct 中的每個(gè)字段初始化為默認(rèn)值。然而,只有當(dāng) struct 用 new 實(shí)例化時(shí),才會(huì)調(diào)用此默認(rèn)構(gòu)造函數(shù)。例如,下面的代碼使用 Int32 的默認(rèn)構(gòu)造函數(shù),因此您可以確信整數(shù)已初始化:
int i = new int(); Console.WriteLine(i);
不過(guò),下面的代碼卻會(huì)導(dǎo)致編譯器錯(cuò)誤,因?yàn)樗鼪](méi)有使用 new,而且嘗試使用尚未初始化的對(duì)象:
int i; Console.WriteLine(i);
或者,基于 structs 的對(duì)象(包括所有內(nèi)置數(shù)值類(lèi)型)可以初始化或賦值后使用,如下面的示例所示:
int a = 44; // Initialize the value type... int b; b = 33; // Or assign it before using it. Console.WriteLine("{0}, {1}", a, b);
因此對(duì)值類(lèi)型調(diào)用默認(rèn)構(gòu)造函數(shù)不是必需的。
類(lèi)和 structs 都可以定義具有參數(shù)的構(gòu)造函數(shù)。帶參數(shù)的構(gòu)造函數(shù)必須通過(guò) new 語(yǔ)句或 base 語(yǔ)句來(lái)調(diào)用。類(lèi)和 structs 還可以定義多個(gè)構(gòu)造函數(shù),并且二者均不需要定義默認(rèn)構(gòu)造函數(shù)。例如:
public class Employee { public int salary; public Employee(int annualSalary) { salary = annualSalary; } public Employee(int weeklySalary, int numberOfWeeks) { salary = weeklySalary * numberOfWeeks; } }
可以使用下列語(yǔ)句中的任一個(gè)語(yǔ)句來(lái)創(chuàng)建此類(lèi):
Employee e1 = new Employee(30000); Employee e2 = new Employee(500, 52);
構(gòu)造函數(shù)可以使用 base 關(guān)鍵字來(lái)調(diào)用基類(lèi)的構(gòu)造函數(shù)。例如:
public class Manager : Employee { public Manager(int annualSalary) : base(annualSalary) { //Add further instructions here. } }
在此示例中,基類(lèi)的構(gòu)造函數(shù)在執(zhí)行構(gòu)造函數(shù)塊之前被調(diào)用。 base 關(guān)鍵字可帶參數(shù)使用,也可不帶參數(shù)使用。構(gòu)造函數(shù)的任何參數(shù)都可用作 base 的參數(shù),或用作表達(dá)式的一部分。有關(guān)更多信息,請(qǐng)參見(jiàn)base(C# 參考)。
在派生類(lèi)中,如果不使用 base 關(guān)鍵字來(lái)顯式調(diào)用基類(lèi)構(gòu)造函數(shù),則將隱式調(diào)用默認(rèn)構(gòu)造函數(shù)(如果有的話(huà))。這意味著下面的構(gòu)造函數(shù)聲明在效果上是相同的:
public Manager(int initialdata) { //Add further instructions here. } public Manager(int initialdata) : base() { //Add further instructions here. }
如果基類(lèi)沒(méi)有提供默認(rèn)構(gòu)造函數(shù),派生類(lèi)必須使用 base 顯式調(diào)用基構(gòu)造函數(shù)。
構(gòu)造函數(shù)可以使用 this 關(guān)鍵字調(diào)用同一對(duì)象中的另一構(gòu)造函數(shù)。和 base 一樣,this 可帶參數(shù)使用也可不帶參數(shù)使用,構(gòu)造函數(shù)中的任何參數(shù)都可用作 this 的參數(shù),或者用作表達(dá)式的一部分。例如,可以使用 this 重寫(xiě)前一示例中的第二個(gè)構(gòu)造函數(shù):
public Employee(int weeklySalary, int numberOfWeeks) : this(weeklySalary * numberOfWeeks) { }
上一示例中對(duì) this 關(guān)鍵字的使用導(dǎo)致此構(gòu)造函數(shù)被調(diào)用:
public Employee(int annualSalary) { salary = annualSalary; }
構(gòu)造函數(shù)可以標(biāo)記為 public、private、protected、internal 或 protectedinternal。這些訪(fǎng)問(wèn)修飾符定義類(lèi)的用戶(hù)構(gòu)造該類(lèi)的方式。有關(guān)更多信息,請(qǐng)參見(jiàn)訪(fǎng)問(wèn)修飾符。
實(shí)例構(gòu)造函數(shù)
使用 new 表達(dá)式創(chuàng)建某個(gè)類(lèi)的對(duì)象時(shí),會(huì)使用實(shí)例構(gòu)造函數(shù)創(chuàng)建和初始化所有實(shí)例成員變量。要初始化靜態(tài)類(lèi)或非靜態(tài)類(lèi)中的靜態(tài)變量,必須定義靜態(tài)構(gòu)造函數(shù)。
下面的示例演示實(shí)例構(gòu)造函數(shù):
class CoOrds { public int x, y; // constructor public CoOrds() { x = 0; y = 0; } }
注意
為了清楚起見(jiàn),此類(lèi)包含公共字段。建議在編程時(shí)不要使用公共字段,因?yàn)檫@種做法會(huì)使程序中任何位置的任何方法都可以不受限制、不經(jīng)驗(yàn)證地訪(fǎng)問(wèn)對(duì)象的內(nèi)部組件。數(shù)據(jù)成員通常應(yīng)當(dāng)為私有的,并且只應(yīng)當(dāng)通過(guò)類(lèi)方法和屬性來(lái)訪(fǎng)問(wèn)。
只要?jiǎng)?chuàng)建基于 CoOrds 類(lèi)的對(duì)象,就會(huì)調(diào)用此實(shí)例構(gòu)造函數(shù)。諸如此類(lèi)不帶參數(shù)的構(gòu)造函數(shù)稱(chēng)為“默認(rèn)構(gòu)造函數(shù)”。然而,提供其他構(gòu)造函數(shù)通常十分有用。例如,可以向 CoOrds 類(lèi)添加構(gòu)造函數(shù),以便可以為數(shù)據(jù)成員指定初始值:
// A constructor with two arguments: public CoOrds(int x, int y) { this.x = x; this.y = y; }
這樣便可以用默認(rèn)或特定的初始值創(chuàng)建 CoOrd 對(duì)象,如下所示:
CoOrds p1 = new CoOrds(); CoOrds p2 = new CoOrds(5, 3);
如果某個(gè)類(lèi)沒(méi)有構(gòu)造函數(shù),則會(huì)自動(dòng)生成一個(gè)默認(rèn)構(gòu)造函數(shù),并使用默認(rèn)值來(lái)初始化對(duì)象字段。例如,int 初始化為 0。有關(guān)默認(rèn)值的更多信息,請(qǐng)參見(jiàn) 默認(rèn)值表(C# 參考)。因此,由于 CoOrds 類(lèi)的默認(rèn)構(gòu)造函數(shù)將所有數(shù)據(jù)成員都初始化為零,因此可以將它完全移除,而不會(huì)更改類(lèi)的工作方式。本主題的稍后部分的示例 1 中提供了使用多個(gè)構(gòu)造函數(shù)的完整示例,示例 2 中提供了自動(dòng)生成的構(gòu)造函數(shù)的示例。
也可以用實(shí)例構(gòu)造函數(shù)來(lái)調(diào)用基類(lèi)的實(shí)例構(gòu)造函數(shù)。類(lèi)構(gòu)造函數(shù)可通過(guò)初始值設(shè)定項(xiàng)來(lái)調(diào)用基類(lèi)的構(gòu)造函數(shù),如下所示:
class Circle : Shape { public Circle(double radius) : base(radius, 0) { } }
在此示例中,Circle 類(lèi)將表示半徑和高度的值傳遞給 Shape(Circle 從它派生而來(lái))提供的構(gòu)造函數(shù)。使用 Shape 和 Circle 的完整示例請(qǐng)見(jiàn)本主題中的示例 3。
示例 1
下面的示例說(shuō)明包含兩個(gè)類(lèi)構(gòu)造函數(shù)的類(lèi):一個(gè)類(lèi)構(gòu)造函數(shù)沒(méi)有參數(shù),另一個(gè)類(lèi)構(gòu)造函數(shù)帶有兩個(gè)參數(shù)。
class CoOrds { public int x, y; // Default constructor: public CoOrds() { x = 0; y = 0; } // A constructor with two arguments: public CoOrds(int x, int y) { this.x = x; this.y = y; } // Override the ToString method: public override string ToString() { return (String.Format("({0},{1})", x, y)); } } class MainClass { static void Main() { CoOrds p1 = new CoOrds(); CoOrds p2 = new CoOrds(5, 3); // Display the results using the overriden ToString method: Console.WriteLine("CoOrds #1 at {0}", p1); Console.WriteLine("CoOrds #2 at {0}", p2); Console.ReadKey(); } }
輸出:
CoOrds #1 at (0,0) CoOrds #2 at (5,3)
示例 2
在此示例中,類(lèi) Person 沒(méi)有任何構(gòu)造函數(shù);在這種情況下,將自動(dòng)提供默認(rèn)構(gòu)造函數(shù),同時(shí)將字段初始化為它們的默認(rèn)值。
public class Person { public int age; public string name; } class TestPerson { static void Main() { Person person = new Person(); Console.WriteLine("Name: {0}, Age: {1}", person.name, person.age); // Keep the console window open in debug mode. Console.WriteLine("Press any key to exit."); Console.ReadKey(); } }
輸出:
Name: , Age: 0
注意,age 的默認(rèn)值為 0,name 的默認(rèn)值為 null。有關(guān)默認(rèn)值的更多信息,請(qǐng)參見(jiàn) 默認(rèn)值表(C# 參考)。
示例 3
下面的示例說(shuō)明使用基類(lèi)初始值設(shè)定項(xiàng)。 Circle 類(lèi)是從通用類(lèi) Shape 派生的,Cylinder 類(lèi)是從 Circle 類(lèi)派生的。每個(gè)派生類(lèi)的構(gòu)造函數(shù)都使用其基類(lèi)的初始值設(shè)定項(xiàng)。
abstract class Shape { public const double pi = Math.PI; protected double x, y; public Shape(double x, double y) { this.x = x; this.y = y; } public abstract double Area(); } class Circle : Shape { public Circle(double radius) : base(radius, 0) { } public override double Area() { return pi * x * x; } } class Cylinder : Circle { public Cylinder(double radius, double height) : base(radius) { y = height; } public override double Area() { return (2 * base.Area()) + (2 * pi * x * y); } } class TestShapes { static void Main() { double radius = 2.5; double height = 3.0; Circle ring = new Circle(radius); Cylinder tube = new Cylinder(radius, height); Console.WriteLine("Area of the circle = {0:F2}", ring.Area()); Console.WriteLine("Area of the cylinder = {0:F2}", tube.Area()); // Keep the console window open in debug mode. Console.WriteLine("Press any key to exit."); Console.ReadKey(); } }
輸出:
Area of the circle = 19.63 Area of the cylinder = 86.39
- C#構(gòu)造函數(shù)詳解
- C# 構(gòu)造函數(shù)如何調(diào)用虛方法
- 淺談C# 構(gòu)造方法(函數(shù))
- C#類(lèi)繼承中構(gòu)造函數(shù)的執(zhí)行序列示例詳解
- C#中構(gòu)造函數(shù)和析構(gòu)函數(shù)用法實(shí)例詳解
- C#靜態(tài)構(gòu)造函數(shù)用法實(shí)例分析
- C#中靜態(tài)構(gòu)造函數(shù)的幾點(diǎn)說(shuō)明介紹
- C#私有構(gòu)造函數(shù)使用示例
- c#只讀字段和常量的區(qū)別,以及靜態(tài)構(gòu)造函數(shù)的使用實(shí)例
- C# 靜態(tài)構(gòu)造函數(shù)使用總結(jié)
- C#構(gòu)造函數(shù)在基類(lèi)和父類(lèi)中的執(zhí)行順序
相關(guān)文章
C#中FormsAuthentication用法實(shí)例
這篇文章主要介紹了C#中FormsAuthentication用法實(shí)例,本文直接給出實(shí)現(xiàn)代碼,需要的朋友可以參考下2015-02-02c#實(shí)現(xiàn)幾種數(shù)據(jù)庫(kù)的大數(shù)據(jù)批量插入
這篇文章主要介紹了c#實(shí)現(xiàn)幾種數(shù)據(jù)庫(kù)的大數(shù)據(jù)批量插入,主要包括SqlServer、Oracle、SQLite和MySQL,有興趣的可以了解一下。2017-01-01C#實(shí)現(xiàn)讀取寫(xiě)入Json文件
這篇文章主要介紹了C#實(shí)現(xiàn)讀取寫(xiě)入Json文件方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-01-01C#中實(shí)現(xiàn)PriorityQueue優(yōu)先級(jí)隊(duì)列的代碼
這篇文章主要介紹了C#中PriorityQueue優(yōu)先級(jí)隊(duì)列的實(shí)現(xiàn),構(gòu)造初始化這部分主要介紹關(guān)鍵的字段和方法,比較器的初始化以及堆的初始化,需要的朋友可以參考下2021-12-12C#學(xué)習(xí)筆記整理_深入剖析構(gòu)造函數(shù)、析構(gòu)函數(shù)
下面小編就為大家?guī)?lái)一篇C#學(xué)習(xí)筆記整理_深入剖析構(gòu)造函數(shù)、析構(gòu)函數(shù)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-09-09C#?winform?窗體控件跨線(xiàn)程訪(fǎng)問(wèn)的實(shí)現(xiàn)
在做winform開(kāi)發(fā)時(shí),如果在子線(xiàn)程中去設(shè)置主線(xiàn)程中UI控件的屬性,會(huì)出現(xiàn)“跨線(xiàn)程調(diào)用異?!?本文就來(lái)介紹一下C#?winform?窗體控件跨線(xiàn)程訪(fǎng)問(wèn)的實(shí)現(xiàn),感興趣的可以了解一下2023-12-12c# Form中的鍵盤(pán)響應(yīng)具體實(shí)現(xiàn)思路
在全屏Form中加上鍵盤(pán)ESC的響應(yīng),實(shí)現(xiàn)的效果就是:全屏中press鍵盤(pán)上的Escape鍵,程序結(jié)束,具體實(shí)現(xiàn)步驟如下,感興趣的朋友可以參考下哈2013-06-06