枚举集合
更新:2007 年 11 月
.NET Framework 提供枚举数作为循环访问一个集合的简单方法。枚举数只读取集合中的数据,无法用于修改基础集合。
有些语言提供一个隐藏直接使用枚举数的复杂性的语句。C# foreach 语句、C++ for each 语句和 Visual Basic For Each 语句使用枚举数。
关于枚举数
一个枚举数展平一个集合,以便可以按顺序访问成员。不同的集合类可能具有不同的序列。例如,ArrayList 的枚举数保留在集合中输入元素时的顺序,而 Hashtable 的枚举数根据元素的哈希代码显示元素。
每一枚举数都基于 IEnumerator 接口或 IEnumerator<T> 泛型接口,这两个接口要求以下成员:
Current 属性指向集合中的当前成员。
MoveNext 属性将枚举数移到集合中的下一成员。
Reset 属性将枚举数移回集合的开始处。Current 被定位于第一个元素的前面。Reset 在泛型 IEnumerator<T> 接口中不可用。
枚举数的行为
最初,枚举数被定位于集合中第一个元素的前面。Reset 还将枚举数返回到此位置。在此位置上,Current 为未定义。因此,您必须调用 MoveNext,以在读取 Current 的值之前将该枚举数提前到该集合的第一个元素。
Current 返回相同的对象,直到调用 MoveNext 或 Reset 为止。MoveNext 将 Current 设置为下一个元素。
如果 MoveNext 超过集合的末尾,枚举数将被定位在集合中最后一个元素之后,而且 MoveNext 返回 false。枚举数处于这个位置时,随后对 MoveNext 的调用也会返回 false。如果对 MoveNext 的最后一次调用返回 false,则 Current 为未定义。
在非泛型集合中,您可以在调用 Reset 后调用 MoveNext,将枚举数移回集合的开始处。
在泛型集合中,您不能再将 Current 设置为集合的第一个元素;而须创建新的枚举数实例。
只要该集合保持不变,枚举数也就保持有效。如果对该集合进行了更改(例如添加、修改或删除了元素),该枚举数将失效(这一变化是不可逆转的),且其行为将变为未定义。
该枚举数不具有独占访问集合的权限;因此,枚举整个集合本质上不是一个线程安全的过程。若要确保枚举过程中的线程安全性,可以在整个枚举过程中锁定集合。若允许多个线程对集合执行读写操作,您必须实现自己的同步。