《Illustrated C# 2012, 4th Edition》Daniel M. Solis 第18章 枚举器与迭代器 笔记
foreach只支持遍历可枚举类型(enumerable type或enumerable)。
可枚举类型指拥有GetEnumerator()方法的类型,GetEnumerator()返回枚举器(enumerator)对象。枚举器可以依次返回集合中的项。
foreach从可枚举类型中通过GetEnumerator()方法获取枚举器,再将枚举器返回的每一项作为迭代变量(iteration variable)。
枚举器是实现了IEnumerator接口或它的泛型版本的类型的对象。
IEnumerator接口包含Current属性和MoveNext()、Reset()方法:
枚举器的初始状态,位置为-1,即集合的第一个元素之前。
访问枚举器时,总是先调用MoveNext(),再访问Current。
当枚举器的位置在最后一个元素之后,MoveNext()返回false,否则返回true。
使用foreach时,编译器生成与以下代码相似的CIL代码:
IEnumerable接口只有一个成员:GetEnumerator()方法。因此实现了IEnumerable接口的类型为可枚举类型。
- 注意:只要拥有GetEnumerator()方法,不实现IEnumerable接口,也是可枚举类型。
与IEnumerator接口一样,IEnumerable接口也存在泛型版本。
非泛型的IEnumerator接口,Current属性返回object类型,因此不是类型安全的。泛型的IEnumerator接口,Current属性返回实际类型,是类型安全的,推荐使用。
泛型的IEnumerator接口不仅实现了非泛型的IEnumerator接口,还实现了IDisposable接口:
泛型的IEnumerable接口实现了非泛型的IEnumerable接口:
C# 2.0还引入了迭代器(iterator)。
依据返回值的类型,迭代器可以生成枚举器或可枚举类型。
yield return语句指定集合的下一项。
yield break语句指定集合没有下一项。
使用迭代器需要引入System.Collections.Generic命名空间。
迭代器生成的枚举器没有实现Reset()方法,调用Reset()方法时抛出System.NotSupportedException异常。
迭代器生成的枚举器是包含4个状态的状态机: