恆定類型(immutable types)其實很簡單,就是一但它們被創建,它們(的值) 就是固定的。如果你驗證一些准備用於創建一個對象的參數,你知道它在驗證狀 態從前面的觀點上看。你不能修改一個對象的內部狀態使之成為無效的。在一個 對象被創建後,你必須自己小心翼翼的保護對象,否則你不得不做錯誤驗證來禁 止改變任何狀態。恆定類型天生就具有線程完全性的特點:多訪問者可同時訪問 相同的內容。如果內部狀態不能修改,那麼就不能給不同的線程提供查看不一致 的數據視圖的機會。恆定類型可以從你的類上安全的暴露出來。調用者不能修改 對象的內部狀態。恆定類型可以很好的在基於哈希代碼的集合上工作。以 Object.GetHashCode()方法返回的值,對同一個實例是必須相同的(參見原則10) ,而這正是恆定類型總能成功的地方。
並不是所有的類型都能成為恆定 類型的。如果它可以,你需要克隆一個對象用於修改任何程序的狀態了。這就是 為什麼同時推薦使用恆定類型和原子類型數據了。把你的對象分解為自然的單一 實體結構。一個Address類型就是的,它就是一個簡單的事,由多個相關的字段 組成。改變其中一個字段就很可能意味著修改了其它字段。一個客戶類型不是一 個原子類型,一個客戶類型可能包含很多小的信息塊:地址,名字,一個或者多 個電話號碼。任何一個互不關聯的信息塊都可以改變。一個客戶可能會在不搬家 的情況下改變電話號碼。而另一個客戶可能在搬了家的情況下保留原來的電話號 碼。還有可能,一個客戶改變了他(她)的名字,而沒有搬家也沒有改電話號碼。 一個客戶類型就不是原子類型;它是由多個不同的恆定的組成部份構成的:地址 ,名字,以及一個成對出現的電話號碼集合。原子類型是單一實體:你很自然的 用原子類型來取代實體內容。這一例外會改變它其中的一個組成字段。
下面就是一個典型的可變地址類的實現:
// Mutable Address structure.
public struct Address
{
private string _line1;
private string _line2;
private string _city;
private string _state;
private int _zipCode;
// Rely on the default system-generated
// constructor.
public string Line1
{
get { return _line1; }
set { _line1 = value; }
}
public string Line2
{
get { return _line2; }
set { _line2 = value; }
}
public string City
{
get { return _city; }
set { _city= value; }
}
public string State
{
get { return _state; }
set
{
ValidateState(value);
_state = value;
}
}
public int ZipCode
{
get { return _zipCode; }
set
{
ValidateZip( value );
_zipCode = value;
}
}
// other details omitted.
}
// Example usage:
Address a1 = new Address( );
a1.Line1 = "111 S. Main";
a1.City = "Anytown";
a1.State = "IL";
a1.ZipCode = 61111 ;
// Modify:
a1.City = "Ann Arbor"; // Zip, State invalid now.
a1.ZipCode = 48103; // State still invalid now.
a1.State = "MI"; // Now fine.