C# 3.0 引入物件初始化器與集合初始化器,讓物件建立與集合填充更簡潔、宣告式。本文詳細解析語法規則、編譯器行為、巢狀初始化、字典初始化等進階主題,附豐富範例。
var student = new StudentName {
FirstName = "Craig",
LastName = "Playstead",
ID = 116
};
重要:若類別無公用預設建構函式(如標記 private 或僅有帶參數建構函式),使用物件初始化器將編譯失敗。
public class StudentName {
// 必須有公用預設建構函式
public StudentName() { }
public StudentName(string first, string last) {
FirstName = first;
LastName = last;
}
public string FirstName { get; set; }
public string LastName { get; set; }
public int ID { get; set; }
public override string ToString() => $"{FirstName} {ID}";
}
// 1. 傳統建構函式
var s1 = new StudentName("Craig", "Playstead"); // ID = 0
// 2. 物件初始化器(僅設定 FirstName, LastName)
var s2 = new StudentName { FirstName = "Craig", LastName = "Playstead" }; // ID = 0
// 3. 僅設定 ID
var s3 = new StudentName { ID = 183 }; // FirstName/LastName 為 null
// 4. 完整設定
var s4 = new StudentName { FirstName = "Craig", LastName = "Playstead", ID = 116 };
Craig 0
Craig 0
183
Craig 116
集合初始化器本質是物件初始化器的序列,適用於實作 IEnumerable 並有 Add 方法的類型(如 List<T>、陣列等)。
var students = new List<StudentName> {
new StudentName { FirstName = "Craig", LastName = "Playstead", ID = 116 },
new StudentName { FirstName = "Shu", LastName = "Ito", ID = 112 },
new StudentName { FirstName = "Gretchen", LastName = "Rivas", ID = 113 },
new StudentName { FirstName = "Rajesh", LastName = "Rotti", ID = 114 }
};
編譯器展開為:
var students = new List<StudentName>();
students.Add(new StudentName { FirstName = "Craig", LastName = "Playstead", ID = 116 });
students.Add(new StudentName { FirstName = "Shu", LastName = "Ito", ID = 112 });
// ...
Dictionary<TKey, TValue> 的 Add 方法接受兩個參數(Key, Value),初始化時需用雙層大括號:
var students = new Dictionary<int, StudentName> {
{ 111, new StudentName { FirstName = "Sachin", LastName = "Karnik", ID = 211 } },
{ 112, new StudentName { FirstName = "Dina", LastName = "Salimzianova", ID = 317 } },
{ 113, new StudentName { FirstName = "Andy", LastName = "Ruth", ID = 198 } }
};
{
{ 111, new StudentName { ... } }, // 外層 {} 包裹 Key-Value,內層 {} 初始化 StudentName
{ 112, new StudentName { ... } },
{ 113, new StudentName { ... } }
}
var order = new Order {
Customer = new Customer { Name = "Acme", Email = "acme@example.com" },
Items = new List<OrderItem> {
new OrderItem { Product = "Widget", Qty = 10 },
new OrderItem { Product = "Gadget", Qty = 5 }
}
};
支援 Dictionary 或自訂索引子:
var dict = new Dictionary<string, int> {
["key1"] = 1,
["key2"] = 2
};
物件初始化器無法設定唯讀屬性(無 set),需透過建構函式。
var point = new { X = 10, Y = 20 }; // 編譯器產生唯讀屬性的匿名型別
Add 呼叫,大量資料時考慮預先 Capacity 或改用陣列/其他方式。| 初始化器類型 | 適用目標 | 核心語法 | 編譯器展開 |
|---|---|---|---|
| 物件初始化器 | 任何有公用預設建構函式的類別/結構 | new T { Prop = val } |
new T() → 指派屬性 |
| 集合初始化器 | 實作 IEnumerable 且有 Add 方法的集合 | new List { new T {..}, new T {..} } |
new List() → Add(item1) → Add(item2)... |
| 字典初始化器 | Dictionary<K,V> 等雙參數 Add | new Dict { {k, new V{..}}, {k, new V{..}} } |
new Dict() → Add(k1, v1) → Add(k2, v2)... |
| 索引子初始化器 | 有索引子的類型(C# 6+) | new T { ["key"] = val } |
new T() → this["key"] = val |
物件與集合初始化器是現代 C# 寫出清晰、可維護代碼的利器。掌握其編譯器語意、巢狀用法與字典雙層大括號規則,能讓資料初始化代碼更具宣告式風格,減少樣板代碼,提升可讀性。