首先看一段代码
int[] arr = new int[] { 1, 2, 3, 4, 5 };
foreach(int ele in arr)
{
Console.Write(ele + " ");
}
输出是“1,2,3,4,5”。问题来了,为什么foreach语句能够依次读取出数组arr中的元素呢?这是因为,数组arr能为foreach提供一个枚举器。
那什么是枚举器?枚举器就是实现IEnumerator接口的类对象。IEnumerator接口的定义如下:
public interface IEnumerator
{
object Current { get; }
bool MoveNext();
void Reset();
}
数组arr为什么能为foreach提供枚举器呢?因为数组类型是可枚举类型,可枚举类型提供了GetEnumerator()方法用于返回当前正在使用的枚举器。而GetEnumerator()方法是IEnumerable接口的唯一成员。也就是说,可枚举类型是指实现了IEnumerable接口的类型。
回过头来,看第一段代码的执行过程:
- 系统自动调用arr.GetEnumerator(),返回一个Enumerator引用。
- 调用Enumerator引用的MoveNext()方法。
- 如果MoveNext()方法返回true,调用Enumerator引用的Current属性获取数组中的当前元素,用于foreach循环。
- 重复2,3循环,直至MoveNext()方法返回false;
也就是说,第一段代码等效下列代码:
int[] arr = new int[] { 1, 2, 3, 4, 5 };
IEnumerator ie = arr.GetEnumerator();
while (ie.MoveNext())
{
Console.Write("{0} ", ie.Current);
}
Console.WriteLine();
最后,IEnumerator接口和IEmerable接口位于System.Collections的命空间中,支持对非泛型集合的简单迭代。