在C#3.0中,一個對象建立運算式可以包含一個對象或集合初始化器,用於初 始化新建立的對象的成員或新建立的集合的元素。
對象建立運算式:
new type (argument-list(可選)) 對象或集合初試化器(可選)
new type 對象或集合初試化器
一個對象建立運算式可以省略構造器參數列表,並將其連同圓括弧一起替換 為一個對象或集合初始化器。省略構造器參數列表並將其連同圓括弧一起替換為 一個對象或集合初始化器等價於指定一個空的參數列表。
在執行一個帶有對象或集合初始化器的對象建立運算式時,首先調用執行個體構 造器,然後執行對象或集合初始化器指定的成員或元素初始化。對象或集合初始 化器不能引用正在初始化的對象執行個體。
20.4.1 引入對象初始器
在傳統的C#中,我們常用兩種方法來對一個類(或者結構體)進行初始化, 一是採用帶有參數的建構函式,另一種則是不採用建構函式,或者建構函式中並 沒有實際地對欄位進行賦值,而是在申請了類的執行個體之後,手動對它的公用屬性 進行賦值。下面是一個二維空間的幾何點例子:
public class Point
{
private int xPos, yPos;
//預設的建構函式
public Point()
{
}
public Point(int x, int y)
{
xPos = x;
yPos = y;
}
public int X
{
get { return xPos; }
set { xPos = value; }
}
public int Y
{
get { return yPos; }
set { yPos = value; }
}
public override string ToString()
{
return string.Format("[{0}, {1}]", xPos, yPos);
}
}
對於這個類,按照一般方法,我們會這樣來初始化它:
//調用自訂的建構函式
Point p = new Point(100,200);
//或者手動指定每個屬性
Point p1 = new Point();
p1.X = 100;
p1.Y = 200;
現在我們採用類初始化器的C# 3.0代碼則可以寫成下面的樣子:
var p1 = new Point { X = 100, Y = 200 };
Point p = new Point { X = 100, Y = 200 };
其中第一個是隱式類型變數。這裡並沒有顯式調用Point的建構函式,僅僅是 將值設給了公用的X和Y屬性。在這裡,類型的預設建構函式被調用,緊跟著將值 賦給指定的屬性。從這一點上說,最後這兩個執行個體實際上就是第一個執行個體的簡化 寫法。
從上面的例子中,我們可以看出:
l 對象初始化器由一系列的成員初始化器構成,包圍在{和}記號中,並用逗 號進行分隔。每個成員初始化器以對象的一個可訪問的域或屬性的名字開始,後 跟一個等號,之後是一個運算式或一個對象或集合初始化器。如果對象初始化其 中包括了對同一個域或屬性的多於一個的成員初始化器,將會發生錯誤。
l 在等號後面指定了運算式的成員初始化器的處理與域和屬性的賦值一致。
l 在等號後面指定了對象初始化器的成員初始化器也是對一個嵌套對象的初 始化。與為域或屬性賦一個新值不同,對象初始化器中的賦值被視為對域或屬性 的成員進行賦值。一個具有實值型別的屬性不能通過這種構造來進行初始化。
l 在等號後面指定了集合初始化器的成員初始化器也是對一個嵌套集合的初 始化。與為域或屬性賦一個新的集合不同,初始化器中給定的元素將被添加到域 或屬性所引用的集合中。該域或屬性必須是一個滿足下一節所指定的需求的集合 類型。
l 對象初時化器是利用了編譯器對對象中的對外可見的欄位或屬性進行按序 賦值,在編譯還是隱式調用了建構函式,對欄位或屬性的賦值可以是一個或是多 個。