程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#集合--ICollection接口和IList接口

C#集合--ICollection接口和IList接口

編輯:C#入門知識

雖然列舉接口提供了一個協議,用於向前的方式遍歷集合,但它們沒有提供一種機制來確定集合的大小,通過索引訪問集合的成員,搜索集合,或修改集合。為了實現這些功能,.NET Framework定義了ICollection,IList和IDictionary接口。每個接口都有Generic的接口和非Generic的接口,請注意非Generic多數用於支持遺留代碼。

這些接口的繼承掛關系如下圖所示:

Generic的接口和非Generic的接口之間的差距超出了你的預期,特別是ICollection和ICollection<T>。這是由於歷史原因造成的,因為Generic類型是C# 2.0才引入的,所以Generic吸取了非Generic接口的經驗和教訓,從而設計了與之不同的但更優秀的接口。正式由於這個原因,ICollection<T>並沒有派生自ICollection,同樣地,IList<T>也沒有派生自IList, IDictionary<TKey,TValue>也沒有派生自IDinctionary。因此集合類可以同時實現Generic的接口和非Generic的接口。(事實上,集合類一般都實現了兩個類型接口,比如class Collection<T>: IList<T>, IList,有比如List<T> : IList<T>, System.Collections.IList)。

 

ICollection<T>和ICollection

ICollection<T>是可以統計集合中對象的標准接口。該接口可以確定集合的大小(Count),集合是否包含某個元素(Contains),復制集合到另外一個數組(ToArray),集合是否是只讀的(IsReadOnly)。如果一個集合是可編輯的,那麼可以調用Add,Remove和Clear方法操作集合中的元素。因為該接口繼承IEnumerable<T>,所以可以使用foreach語句遍歷集合。該接口的定義如下

  ICollection<T> : IEnumerable<T>
     Count {  IsReadOnly {  
     CopyTo(T[] array, 

    

而非Generic的ICollection定義如下:

  CopyTo(Array array,  Count {  IsSynchronized { 

與ICollection<T>相比較,ICollection實現了計算集合元素數目的功能,但明沒有提供更改集合的功能。此外,ICollection還提供了同步的功能。而ICollection<T>則取消了同步的功能,這是因為對於Generic的集合,它們本身是線程安全的。

這兩個接口既簡單又容易實現。假如要實現一個只讀的ICollection<T>,那麼在Add,Remove,和Clear方法中拋出異常即可。

這些接口通常與任何IList或IDictionary接口中的任意一個一起實現。

 

IList<T>和IList

如果想通過位置獲取集合元素,那麼IList<T>就是此類集合的標准接口。此外,由於IList<T>繼承了ICollection<T>和IEnumerable<T>,所以此接口還提供了根據位置讀取或寫入元素,或者在指定的位置插入或刪除元素。IList<T>定義如下

  IList<T> : ICollection<T>[ index] { ;  Insert( RemoveAt(

IndexOf方法在集合上執行線性搜索,如果沒有發現指定元素,那麼返回-1。

List類的IndexOf方法的實現:(List.IndexOf(T item)調用Array.IndexOf(_items, item, index, _size - index),然後調用EqualityComparer<T>.Default.IndexOf(array, value, startIndex, count))

   IndexOf(T[] array, T value,  startIndex,  endIndex = startIndex + ( i = startIndex; i < endIndex; i++ (Equals(array[i], value))  -

而非Generic的IList則包含了更多成員,因為它繼承ICollection

 [ index] {  ; IsReadOnly  {  IsFixedSize  {  Insert( RemoveAt(

IList接口的Add方法返回一個整數,這是加到集合中元素的位置。而IList<T>接口的Add方法返回值為空。

C#中,List<T>就是典型的既實現了IList<T>又實現了IList的類。

  List<T> : IList<T>, System.Collections.IList, IReadOnlyList<T>

C#數組也實現了generic和非generic的IList接口。C#中Array類的部分代碼(實現IList接口的代碼)

    {    {  [ {   NotSupportedException(Environment.GetResourceString( Array.IndexOf(, value) >= .GetLowerBound(, .GetLowerBound(),  Array.IndexOf( IList.Insert(  NotSupportedException(Environment.GetResourceString(  NotSupportedException(Environment.GetResourceString( IList.RemoveAt(  NotSupportedException(Environment.GetResourceString(

而Generic的IList<T>是在sealed class SZArrayHelper中實現的。SZ(Single dimensional, Zero-based)。請注意,如果你在技術與上調用add或者remove方法,那麼會返回NotSupportedException異常

 

IReadonlyList<T>

為了與Windows運行時的制度集合互操作,Framework4.5引入了一個新的集合接口IReadOnlyList<T>。該接口自身就非常有用,也可以看作IList的縮減版,對外只公開用於只讀的操作。其定義如下:

  IReadOnlyCollection< T> : IEnumerable<T> Count {   IReadOnlyList< T> : IReadOnlyCollection<T>[ index] { 

因為類型參數僅僅用於輸出位置,所以其標記為協變(covariant)。比如,一個cats列表,可以看作一個animals的只讀列表。相反,在IList<T>中,T沒有標記為協變,因為T應用於輸入和輸出位置。

你可能認為IList<T>派生自IReadonlyList<T>,然後,微軟並沒有這麼做,這是因為這麼做就要求把IList<T>的成員移動到IReadonlyList<T>,這就給CLR4.5帶來重的變化(程序員需要重新編輯程序以避免運行時錯誤)。實際上,微軟在IList<T>的實現類中手動地添加了對IReadonlyList<T>接口的實現。

在Windows運行時中IVectorView<T>與.NET Framework的IReadonlyList<T>相對應。

 

 

參考

線性搜索(Linear Search): http://en.wikipedia.org/wiki/Linear_search; http://blog.teamleadnet.com/2012/02/quicksort-binary-search-and-linear.html

數組實現IList<T>: http://stackoverflow.com/questions/11163297/how-do-arrays-in-c-sharp-partially-implement-ilistt/11164210#11164210

數組的奧秘: http://stackoverflow.com/questions/19914523/mystery-behind-system-array

協變: http://stackoverflow.com/questions/2719954/understanding-covariant-and-contravariant-interfaces-in-c-sharp

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved