前兩天發布了《隱藏接口實現 及 ReadOnlyDictionary》一文,有不少朋友提 出疑問。其中一個主要問題就是,這樣做真的可以實現“只讀”嗎?如果還有其 他變量引用了ReadOnlyDictionary所包裝的普通字典,依然可以通過另外這個變 量來修改字典中的內容。有朋友甚至提到了,可以在創建ReadOnlyDictionary時 ,將原有字典中的內容復制出一份,來做到真正的“只讀”。
其實,這些主要是因為我對這個類的應用場景沒有介紹清楚的緣故。其實我這 裡提到的ReadOnlyDictionary也好,.NET提供的ReadOnlyCollection也罷,其目 的並不是讓整個字典(或集合)真的“只讀”,而是希望某些具有字典(或集合 )性質類成員,能夠做到“在當前類中可讀寫,在類的外部只讀”。
考慮這樣一個場景,我要實現一個FileStructure類,表示文件結構,其中包 含了多個Field。每個FileStructure裡的每個Field都具有不同的名字,我希望用 戶能夠用名字檢索到對應的字段,所以最好的方式是將字段保存在一個字典中。
public class FileStructure
{
public Dictionary<string, Field> Fields
{
get { return _fields; }
}
public FileStructure()
{
_fields = new Dictionary<string, Field> ();
_fields.Add("DosHeader", new Field(...));
_fields.Add("PEHeader", new Field(...));
_fields.Add ("OptionalHeader", new Field(...));
}
private Dictionary<string, Field> _fields;
}
上面的代碼雖然保證了Fields屬性是只讀的——可以確保用戶無法用自己的字 典實例來替換FileStructure所有的——但卻不能防止用戶自己向Fields屬性中添 加其他字段。
如果使用ReadOnlyDictionary,就能很好地避免這一問題。
public class FileStructure
{
public ReadOnlyDictionary<string, Field> Fields // Change ‘Dictionary’ to ‘ReadOnlyDictionary’
{
get { return _roFields; } // Change '_fields' to '_roFields'
}
public FileStructure()
{
_fields = new Dictionary<string, Field>();
_roFields = new ReadOnlyDictionary<string, Field>(_fields); // Added
_fields.Add("DosHeader", new Field(...));
_fields.Add("PEHeader", new Field(...));
_fields.Add ("OptionalHeader", new Field(...));
}
private Dictionary<string, Field> _fields;
private ReadOnlyDictionary<string, Field> _roFields; // Added
}
現在,就不怕用戶“擅自”修改字典中的內容了。
在ReadOnlyDictionary的實現中,並沒有復制所包裝的字典中的內容。這樣做 的好處是顯而易見的——其一,節省空間。其二,ReadOnlyDictionary能夠及時 反映內部普通字典上發生的變化;也就是說,如果在類的“內部”向字典中添加 了新值,或修改了某些條目,則在類的“外部”可以從之前拿到的只讀字典中, 訪問到這些變化過的條目。