列舉集合
.NET Framework 會提供列舉程式做為逐一查看集合的簡易方式。 列舉程式只讀取集合中的資料;它們不能用來修改基礎集合。
某些語言會提供陳述式,該陳述式會隱藏直接使用列舉程式的複雜性。 C# foreach 陳述式、C++ for each 陳述式以及 Visual Basic For Each 陳述式都會使用列舉程式。
關於列舉程式
列舉程式使集合扁平化,以致可以循序存取成員。 不同集合類別可能會有不同順序。 例如,ArrayList 的列舉程式會保留項目進入集合的順序,而 Hashtable 的列舉程式則會根據項目的雜湊程式碼來顯示項目。
每一個列舉程式都是以 IEnumerator 介面或 IEnumerator<T> 泛型介面為基礎,此介面需要下列成員:
Current 屬性,會指向集合中的目前成員。
MoveNext 屬性,會將列舉程式移到集合中的下一個成員。
Reset 屬性,會將列舉程式移回集合的開頭。 Current 位於第一個項目之前。 泛型 IEnumerator<T> 介面並不提供 Reset 功能。
列舉程式的行為
列舉程式一開始會位於集合中第一個項目之前, Reset 也會將列舉程式帶回這個位置。 這個位置上的 Current 未定義。 因此您必須在讀取 Current 的值之前,先呼叫 MoveNext 將列舉程式推進到集合的第一個項目。
Current 會傳回相同物件,直到呼叫 MoveNext 或 Reset 為止。 MoveNext 會將 Current 設為下一個項目。
如果 MoveNext 到達集合尾端,列舉程式便會置於集合的最後一個項目之後,且 MoveNext 會傳回 false。 當列舉程式位於這個位置時,後續對 MoveNext 的呼叫也會傳回 false。 如果最後一個對 MoveNext 的呼叫傳回 false,則表示 Current 未定義。
在非泛型集合中,您可以呼叫後面跟著 MoveNext 的 Reset,將列舉程式移回集合開頭。
在泛型集合中,您無法再將 Current 設定成集合的第一個項目,只能新建一個列舉程式執行個體。
只要集合保持不變,列舉程式將保持有效。 如果對集合進行變更,例如新增、修改或刪除項目,列舉程式將失效且無法復原,而且其行為會變成未定義。
列舉程式對集合沒有獨佔存取權,因此在集合中逐一列舉,本質上就不是個執行緒安全的程序。 若要確保列舉期間的執行緒安全,您可以在整個列舉期間鎖定集合。 若要允許多重執行緒存取集合以進行讀寫,您必須實作自己的同步處理,或使用 System.Collections.Concurrent 命名空間中的其中一個安全執行緒集合類別。 System.Collections.Concurrent.ConcurrentQueue<T> 和 System.Collections.Concurrent.ConcurrentStack<T> 類別會先擷取項目的快照,然後再列舉項目,避免另一個執行緒變動集合。 System.Collections.Concurrent.ConcurrentDictionary<TKey, TValue> 類別不會擷取快照。
System.Collections.Concurrent.BlockingCollection<T> 類別會提供名為 GetConsumingEnumerable 的列舉程式方法,這個方法會在列舉項目時,從集合中移除項目,藉以變動集合。