1. 程式人生 > >B.1 介面

B.1 介面

  幾乎所有要學習的介面都位於 System.Collections.Generic 名稱空間。圖B-1展示
了.NET4.5以前主要介面間的關係,此外還將非泛型的 IEnumerable 作為根介面包括了進來。為
避免圖表過於複雜,此處沒有包含.NET 4.5的只讀介面。


  正如我們已經多次看到的,最基礎的泛型集合介面為 IEnumerable<T> ,表示可迭代的項的
序列。 IEnumerable<T> 可以請求一個 IEnumerator<T> 型別的迭代器。由於分離了可迭代序列
和迭代器,這樣多個迭代器可以同時獨立地操作同一個序列。如果從資料庫角度來考慮,表就是
IEnumerable<T> ,而遊標是 IEnumerator<T> 。本附錄僅有的兩個可變(variant)集合介面
為.NET 4中的 IEnumerable<out T> 和 IEnumerator<out T> ;其他所有介面的元素型別值均
可雙向進出,因此必須保持不變。


  接下來是 ICollection<T> ,它擴充套件了 IEnumerable<T> ,添加了兩個屬性( Count 和
IsReadOnly )、變動方法( Add 、 Remove 和 Clear )、 CopyTo (將內容複製到陣列中)和 Contains
(判斷集合是否包含特殊的元素)。所有標準的泛型集合實現都實現了該介面。


  IList<T> 全都是關於定位的:它提供了一個索引器、 InsertAt 和 RemoveAt (分別與 Add
和 Remove 相同,但可以指定位置),以及 IndexOf (判斷集合中某元素的位置)。對 IList<T>
進行迭代時,返回項的索引通常為0、1,以此類推。文件裡沒有完整的記錄,但這是個合理的假設。
同樣,通常認為可以快速通過索引對 IList<T> 進行隨機訪問。


  IDictionary<TKey, TValue> 表示一個獨一無二的鍵到它所對應的值的對映。值不必是唯
一的,而且也可以為空;而鍵不能為空。可以將字典看成是鍵/值對的集合,因此
IDictionary<TKey, TValue> 擴充套件了 ICollection<KeyValuePair<TKey, TValue>> 。獲
取值可以通過索引器或 TryGetValue 方法;與非泛型 IDictionary 型別不同,如果試圖用不存
在的鍵獲取值, IDictionary<TKey, TValue> 的索引器將丟擲一個 KeyNotFoundException 。
TryGetValue 的目的就是保證在用不存在的鍵進行探測時還能正常執行。


  ISet<T> 是.NET 4新引入的介面,表示唯一值集。它反過來應用到了.NET 3.5中的
HashSet<T> 上,以及.NET 4引入的一個新的實現—— SortedSet<T> 。


  在實現功能時,使用哪個介面(甚至實現)是十分明顯的。難的是如何將集合作為API的一
部分公開;返回的型別越具體,呼叫者就越依賴於你指定型別的附加功能。這可以使呼叫者更輕
鬆,但代價是降低了實現的靈活性。我通常傾向於將介面作為方法和屬性的返回型別,而不是保
證一個特定的實現類。在API中公開易變集合之前,你也應該深思熟慮,特別是當集合代表的是
物件或型別的狀態時。通常來說,返回集合的副本或只讀的包裝器是比較適宜的,除非方法的全
部目的就是通過返回集合做出變動。