首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Effective C# 原則 7:選擇不可變的原子實值型別(四)

     編輯:關於C語言

可變結構的危隀:暫態無效狀態

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 存取器。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved