這個數組是一個引用類型。PhoneList內部引用的數組,引用 了分配在對象外的數組存儲空間上。開發人員可以通過另一個引用到這個存儲空 間上的對象來修改你的恆定結構。為了避免這種可能,你須要對這個數組做一個 被動拷貝。前面的例子顯示了可變集合的弊端。如果電話類型是一個可變的引用 類型,它還會有更多危害存在的可能。客戶可以修改它在集合裡的值,即使這個 集合是保護,不讓任何人修改。這個被動的拷貝應該在每個構造函數裡被實現, 而不管你的恆定類型裡是否存在引用對象:
// Immutable: A copy is made at construction.
public struct PhoneList
{
private readonly Phone[] _phones;
public PhoneList( Phone[] ph )
{
_phones = new Phone[ ph.Length ];
// CopIEs values because Phone is a value type.
ph.CopyTo( _phones, 0 );
}
public IEnumerator Phones
{
get
{
return _phones.GetEnumerator();
}
}
}
Phone[] phones = new Phone[10];
// initialize phones
PhoneList pl = new PhoneList( phones );
// Modify the phone list:
// Does not modify the copy in pl.
phones[5] = Phone.GeneratePhoneNumber( );
當你返回一個 可變類型的引用時,也應該遵守這一原則。如果你添加了一個屬性用於從 PhoneList結構中取得整個數組的鏈表,這個訪問器也必須實現一個被動拷貝。 詳情參見原則23。
這個復雜的類型表明了三個策略,這是你在初始化你 的恆定對象時應該使用的。這個Address結構定義了一個構造函數,讓你的客戶 可以初始化一個地址,定義合理的構造函數通常是最容易達到的。
你同 樣可以創建一個工廠方法來實現一個結構。工廠使得創建一個通用的值型數據變 得更容易。.Net框架的Color類型就是遵從這一策略來初始化系統顏色的。這個 靜態的方法Color.FromKnownColor()和Color.FromName()從當前顯示的顏色中拷 貝一個給定的系統顏色,返回給用戶。
第三,你可以為那些需要多步操 作才能完成構造函數的恆定類型添加一個伴隨類。.Net框架裡的字符串類就遵從 這一策略,它利用了伴隨類System.Text.StringBuilter。你是使用 StringBuliter類經過多步操作來創建一個字符串。在完成了所有必須步驟生成 一個字符串類後,你從StringBuilter取得了一個恆定的字符串。
(譯注 :.Net裡的string是一但初始化,就不能再修改,對它的任何改動都會生成新的 字符串。因此多次操作一個string會產生較多的垃圾內存碎片,你可以用 StringBuliter來平衡這個問題。)
恆定類型是更簡單,更容易維護的。 不要盲目的為你的每一個對象的屬性創建get和set訪問器。你對這些類型的第一 選擇是把這些數存儲為恆定類型,原子類型。從這些實體中,你可以可以容易的 創建更多復雜的結構。
=================================
小 結:翻譯了幾篇原則,有些句子確實很難理解,自己也感覺翻譯的七不像八不像 的。如果讀者遇到這樣的一些不清楚的句子,可以跳過去,或者看原文。感覺實 在是能力有限。
而且,對於書中的內容,我也並不是完全清楚,很多東 西我自己也是在學習。所以添加的一些譯注也不見得就是完全正確的。例如這一 原則中的DateTime結構,它是不是一個恆定類型,我不敢確定,但從我讀了這一 原則後,加上我對DataTime以及這一原則的理解,覺得這個DateTime結構確實就 是這一原則的實例。後面的原則我大概翻閱了一下,有的深有的淺,後期的翻譯 也會是有些艱難的,但不管怎樣,我都會盡我最大的能力,盡快翻譯完所有原則 。
返回教程目錄