var a1 = new Address();
a1.Line1 = "111 S. Main";
a1.City = "Anytown";
a1.State = "IL";
a1.ZipCode = 61111;
// 修改城市 → 暫態無效:City/State/Zip 不一致
a1.City = "Ann Arbor"; // 此時 State=IL, Zip=61111 不匹配 Ann Arbor
a1.ZipCode = 48103; // State 仍為 IL
a1.State = "MI"; // 才恢復有效
多執行緒下,其他執行緒可能觀測到中間無效狀態。單執行緒若拋出例外(如 Zip 驗證失敗),物件留在損壞狀態。
public readonly struct Address
{
public readonly string Line1;
public readonly string Line2;
public readonly string City;
public readonly string State;
public readonly int ZipCode;
// 僅提供 get 存取器
public string Line1 => _line1;
// ... 其他屬性
}
Address a1 = new Address("111 S. Main", "", "Anytown", "IL", 61111);
// 修改:重新初始化(舊版 C#)
a1 = new Address(a1.Line1, a1.Line2, "Ann Arbor", "MI", 48103);
// C# 9+ with 運算式(編譯器自動複製其他欄位)
a1 = a1 with { City = "Ann Arbor", State = "MI", ZipCode = 48103 };
Address a1 = ...;
a1 = new Address(...); // 這是賦值運算
// 右邊建構函式若拋例外,賦值不執行,a1 保持原值
這就是為什麼更新邏輯必須放在建構函式,而非個別 set 存取器。