我需要在自己的類中維護集合語義。難道你不能解釋什麼是集合語義?據我所知,它是一組必須在課堂上實施的接口。這是真的嗎?如果是的話 - 什麼恰恰我必須在課堂上實現和爲什麼?這兩個接口(ICollection和IEnumerable)是否足夠,或者這些只是最必要的接口?什麼是集合語義(在.NET中)?
我正在使用this article作爲幫助對一個循環鏈表進行編程。
我需要在自己的類中維護集合語義。難道你不能解釋什麼是集合語義?據我所知,它是一組必須在課堂上實施的接口。這是真的嗎?如果是的話 - 什麼恰恰我必須在課堂上實現和爲什麼?這兩個接口(ICollection和IEnumerable)是否足夠,或者這些只是最必要的接口?什麼是集合語義(在.NET中)?
我正在使用this article作爲幫助對一個循環鏈表進行編程。
有.NET中許多集合類型,它們都具有一些共同的行爲,例如:
foreach
Count
財產Add
方法此行爲預期來自集合類型,您猜對了:全部位於ICollection<T>
接口中。讓我們來看看接口層次:
IEnumerable<T>
允許類與foreach
ICollection<T>
枚舉是IEnumerable<T>
代表一個集合:
Count
Add
/Remove
/Clear
收藏品IsReadOnly
應該返回true
Contains
/CopyTo
。IList<T>
是一個ICollection<T>
允許通過索引訪問項目。
Insert
/RemoveAt
IndexOf
哪些接口應實現是語義問題:
IEnumerable<T>
只是一個可枚舉的序列。它只應該通過消費代碼枚舉一次,因爲你永遠不知道它是如何在多個枚舉上表現的。像ReSharper這樣的工具甚至會發出警告,如果您多次枚舉IEnumerable<T>
。
當然,大多數時候你可以安全地枚舉它多次,但有些時候你不應該這樣做。例如,枚舉可以執行SQL查詢(例如,考慮Linq-to-SQL)。
您通過定義一個函數來實現IEnumerable<T>
:GetEnumerator
返回en IEnumerator<T>
。枚舉器是一種對象,它是一種指向序列中當前元素的指針。它可以返回這個值Current
,並且它可以移動到MoveNext
的下一個元素。它也是一次性的(並且在枚舉結束時由foreach
處置)。
讓我們分解一個foreach
循環:
IEnumerable<T> sequence = ... // Whatever
foreach (T item in sequence)
DoSomething(item);
這等同於以下內容:
IEnumerator<T> enumerator = null;
try
{
enumerator = sequence.GetEnumerator();
while (enumerator.MoveNext())
{
T item = enumerator.Current;
DoSomething(item);
}
}
finally
{
if (enumerator != null)
enumerator.Dispose();
}
爲了記錄在案,實施IEnumerable
沒有嚴格要求,使一類可與foreach
。鴨子打字在這裏就足夠了,但我太離譜了。
當然,你可以用yield
關鍵字很容易地實現模式:
public static IEnumerable<int> GetAnswer()
{
yield return 42;
}
這將創建將實施IEnumerable<int>
給你,讓你不必爲私有類。
ICollection<T>
代表一個集合,它可以多次安全地枚舉。但你真的不知道它是什麼樣的集合。它可以是一個集合,一個列表,一個字典,不管。
這是集合的語義。
一些例子:
T[]
- 它實現ICollection<T>
即使你不能Add
/Remove
List<T>
HashSet<T>
- 集合的一個很好的例子,但不是列表Dictionary<TKey, TValue>
- 是的,這是一個ICollection<KeyValuePair<TKey, TValue>>
LinkedList<T>
ObservableCollection<T>
IList<T>
讓你知道的集合是一個可以讓你通過索引訪問元素容易的那種(即在O(1)時間)。
對於您的循環鏈表,情況並非如此,因爲它不僅需要O(n)時間,但首先沒有有意義的索引。
一些例子:
T[]
List<T>
ObservableCollection<T>
注意HashSet<T>
和Dictionary<TKey, TValue>
不再在列表中的實例。這些不是列表。 LinkedList<T>
在語義上是一個列表,但它不提供按索引訪問的時間(它需要O(n))。
我應該提到只有在.NET 4.5中寫入的等價物:IReadOnlyCollection<out T>
,IReadOnlyList<out T>
。這些對他們提供的協方差很好。
非常感謝您的詳盡解釋!現在我的想法更清晰了。 – 2014-10-05 12:34:28
鏈接的文章已經實現了ICollection。 – 2014-10-05 11:24:54
是的,我知道。這對我來說有點困惑。 @HenkHolterman – 2014-10-05 12:08:05