C# 3.0 引入物件初始化器與集合初始化器,大幅簡化物件建立與賦值程式碼,配合 LINQ 使用時更能避免冗長的建構式。本文詳細探討四大核心問題:部分賦值、internal 成員存取、與建構函式配合、賦值執行順序。
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
private int test01 = 25;
internal int test02;
}
// 使用
var person = new Person
{
FirstName = "Scott",
LastName = "Guthrie",
test02 = 56 // 可存取 internal 成員
};
允許。 未指定的屬性保持預設值(null、0、false 等)。
internal 成員嗎?允許。 同組件內可存取 internal 屬性/欄位。private 成員仍不可存取。
可。 先呼叫建構函式,再套用初始化器賦值。
// Cookie 建構函式需 name、value
var cookie = new System.Net.Cookie("MyCookie", "Jose")
{
Comment = "a cookie" // 初始化器補充 Comment
};
建構函式先執行,初始化器後執行。
var cookie = new System.Net.Cookie("MyCookie", "Jose")
{
Name = "test02", // 初始化器覆蓋建構函式設定的 Name
Comment = "a cookie"
};
Console.WriteLine(cookie.Name); // 輸出:test02
執行順序:
List people = new List
{
new Person { FirstName = "Scott", LastName = "Guthrie", Age = 32 },
new Person { FirstName = "Bill", LastName = "Gates", test02 = 85 },
new Person { FirstName = "Susanne", Age = 32 }, // 部分賦值
null // 允許 null 元素
};
null 嗎?可。 如上例所示。
Hashtable / Dictionary 嗎?可。 使用雙大括號:外層為集合,內層為鍵值對(每對本質是物件初始化器)。
Hashtable pp = new Hashtable
{
{ 1, new Person { FirstName = "Scott", LastName = "Guthrie", Age = 32 } },
{ 2, new Person { FirstName = "Bill", LastName = "Gates", test02 = 85 } },
{ 3, new Person { FirstName = "Susanne", Age = 32 } },
{ 4, null } // 值可為 null
};
Dictionary 同理:
var dict = new Dictionary
{
[1] = new Person { FirstName = "Scott", Age = 32 },
[2] = new Person { FirstName = "Bill", Age = 55 }
};
物件初始化器編譯後等價於:
// 原始碼
var p = new Person { FirstName = "A", Age = 20 };
// 編譯器生成(簡化)
Person __temp = new Person();
__temp.FirstName = "A";
__temp.Age = 20;
var p = __temp;
集合初始化器編譯後等價於:
// 原始碼
var list = new List { 1, 2, 3 };
// 編譯器生成
List __temp = new List();
__temp.Add(1);
__temp.Add(2);
__temp.Add(3);
var list = __temp;
readonly 欄位:唯讀欄位僅能在建構函式設定,初始化器無法賦值物件/集合初始化器是 C# 3.0 為 LINQ 鋪路的關鍵語法糖,掌握其部分賦值、internal 存取、建構函式配合、執行順序四大特性,能寫出更優雅、可維護的物件建立程式碼。