您可以宣告實例建構函式,以指定當您使用 new 表達式建立型別的新實例時所執行的程序代碼。 若要在非靜態類別中初始化 靜態 類別或靜態變數,您可以定義 靜態建構函式。
如下列範例所示,您可以在一種類型中宣告數個實例建構函式:
class Coords
{
public Coords()
: this(0, 0)
{ }
public Coords(int x, int y)
{
X = x;
Y = y;
}
public int X { get; set; }
public int Y { get; set; }
public override string ToString() => $"({X},{Y})";
}
class Example
{
static void Main()
{
var p1 = new Coords();
Console.WriteLine($"Coords #1 at {p1}");
// Output: Coords #1 at (0,0)
var p2 = new Coords(5, 3);
Console.WriteLine($"Coords #2 at {p2}");
// Output: Coords #2 at (5,3)
}
}
在上述範例中,第一個無參數建構函式會呼叫兩個自變數相等 0的第二個建構函式。 若要這樣做,請使用 this 關鍵詞。
當您在衍生類別中宣告實例建構函式時,您可以呼叫基類的建構函式。 若要這樣做,請使用 base 關鍵詞,如下列範例所示:
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() => pi * x * x;
}
class Cylinder : Circle
{
public Cylinder(double radius, double height)
: base(radius)
{
y = height;
}
public override double Area() => (2 * base.Area()) + (2 * pi * x * y);
}
class Example
{
static void Main()
{
double radius = 2.5;
double height = 3.0;
var ring = new Circle(radius);
Console.WriteLine($"Area of the circle = {ring.Area():F2}");
// Output: Area of the circle = 19.63
var tube = new Cylinder(radius, height);
Console.WriteLine($"Area of the cylinder = {tube.Area():F2}");
// Output: Area of the cylinder = 86.39
}
}
無參數建構函式
如果 類別 沒有明確的實例建構函式,C# 會提供無參數建構函式,讓您可用來具現化該類別的實例,如下列範例所示:
public class Person
{
public int age;
public string name = "unknown";
}
class Example
{
static void Main()
{
var person = new Person();
Console.WriteLine($"Name: {person.name}, Age: {person.age}");
// Output: Name: unknown, Age: 0
}
}
該建構函式會根據對應的初始化表達式,初始化實例欄位和屬性。 如果欄位或屬性沒有初始化運算式,其值會設定為欄位或屬性類型的 預設值 。 如果您在類別中宣告至少一個實例建構函式,C# 就不會提供無參數建構函式。
結構類型一律提供無參數建構函式。 無參數建構函式可以是隱含的無參數建構函式,其會初始化型別的預設值,或是明確宣告的無參數建構函式。 如需詳細資訊,請參閱
主要建構函式
從 C# 12 開始,您可以在類別和結構中宣告 主要建構 函式。 您可以在類型名稱之後的括號中放置任何參數:
public class NamedItem(string name)
{
public string Name => name;
}
主要建構函式的參數在宣告型別的整個範圍內都有效。 它們可以初始化屬性或欄位。 它們可作為方法或區域函式中的變數。 它們可以傳遞至基底建構函式。
主要建構函式表示任何型別實例都需要這些參數。 任何明確寫入的 this(...) 建構函式都必須使用初始化表達式語法來叫用主要建構函式。 這可確保所有建構函式都會明確指派主要建構函式參數。 對於任何 class 類型,包括 record class 類型,當主要建構函式存在時,不會發出隱含無參數建構函式。 對於任何 struct 類型,包括 record struct 型別,隱含無參數建構函式一律會發出,而且一律會將所有字段,包括主要建構函式參數初始化為0位模式。 如果您撰寫明確的無參數建構函式,則必須叫用主要建構函式。 在此情況下,您可以為主要建構函式參數指定不同的值。 下列程式代碼顯示主要建構函式的範例。
// name isn't captured in Widget.
// width, height, and depth are captured as private fields
public class Widget(string name, int width, int height, int depth) : NamedItem(name)
{
public Widget() : this("N/A", 1,1,1) {} // unnamed unit cube
public int WidthInCM => width;
public int HeightInCM => height;
public int DepthInCM => depth;
public int Volume => width * height * depth;
}
您可以藉由在 屬性上指定 method: 目標,將屬性新增至合成的主要建構函式方法:
[method: MyAttribute]
public class TaggedWidget(string name)
{
// details elided
}
如果您未指定 method 目標,屬性會放在 類別上,而不是方法。
在 class 和 struct 類型中,主要建構函式參數可在類型主體中的任何位置使用。 參數可以實作為擷取的私人欄位。 如果參數的唯一參考是初始化表達式和建構函式呼叫,則不會在私用欄位中擷取該參數。 在型別的其他成員中使用 會導致編譯程式擷取私用字段中的參數。
如果類型包含 record 修飾詞,編譯程式會改用與主要建構函式參數相同的名稱合成公用屬性。 對於 record class 類型,如果主要建構函式參數使用與基底主要建構函式相同的名稱,該屬性是基底 record class 類型的公用屬性。 它不會在衍生 record class 型別中重複。 這些屬性不會針對非record 類型產生。