1、枚举器和可枚举类型 foreach语句可以循环一次取数组中元素的原理:数组可以提供一个枚举器Enumerator的对象,枚举器可以知道元素的次序。 获取一个对象枚举器的方法是调用对象的GetEnumerator方法。实现了GetEnumerator方法的类型叫做可枚举类型Enumerable。 2 IEnumerator接口 实现了IEnumerator接口的枚举器包含3个函数成员:Current、MoveNext以及ReSet 使用foreach语句其实程序内部运行的代码如下: int[] MyArray = { 10,11,12,13}; IEnumerator ie = MyArray.GetEnumerator(); while (ie.MoveNext()) { int i = (int)ie.Current; Console.WriteLine(i.ToString()); } 一个使用IEnumerator和IEnumerable的例子: class ColorEnumerator : IEnumerator { string[] _colors; int _position = -1; public ColorEnumerator(string[] theColors) { _colors = newstring[theColors.Length]; for (int i = 0; i < theColors.Length; i++) _colors[i] = theColors[i]; } public object Current//实现IEnumerator接口的三个成员 { get { if (_position == -1) throw new InvalidOperationException(); if (_position >= _colors.Length) throw new InvalidOperationException(); return _colors[_position];//返回的是object类型 } } public bool MoveNext() { if (_position < _colors.Length - 1) { _position++; returntrue; } else returnfalse; } publicvoid Reset() { _position = -1; } } class Spectrum : IEnumerable//可枚举类Spectrum,它的枚举器是ColorEnumerator { string[] Colors = { "violet","blue","red","yellow","green"}; public IEnumerator GetEnumerator() { return new ColorEnumerator(Colors); } } class Program { static void Main(string[] args) { Spectrum spectrum = new Spectrum(); foreach (string color in spectrum) { Console.WriteLine(color); } } } 3 泛型枚举接口 IEnumerator<T> IEnumerable<T> publicclassColorEnumberatorList : IEnumerator<String> 实现一个泛型枚举器接口 { string[] Colors; int Position = -1; publicstring Current// 当前元素 泛型 { get { return Colors[Position]; } } objectIEnumerator.Current/// 显示实现Current 非泛型 { get { return Colors[Position]; } } publicbool MoveNext() /// 移动到下一个 { if (Position < Colors.Length - 1) { Position++; returntrue; } else { returnfalse; } } publicvoid Reset() /// 重置 { Position = -1; } publicvoid Dispose()/// 销毁操作 { } public ColorEnumberatorList(string[] theColors) /// 构造函数 { Colors = newstring[theColors.Length]; for (int i = 0; i < theColors.Length; i++) { Colors[i] = theColors[i]; } } } publicclass Spectrum : IEnumerable<string> /// 泛型可枚举类 实现 { string[] Colors = { "Red", "Yellow", "Blue" }; publicIEnumerator<string> GetEnumerator() /// IEnumerable<T>版本" { returnnewColorEnumberatorList(Colors); } IEnumeratorIEnumerable.GetEnumerator() /// 显示实现 IEnumerable版本 { returnnewColorEnumberatorList(Colors); } } class泛型枚举器接口 { staticvoid Main(string[] args) { Spectrum spectrum = newSpectrum(); foreach (string color in spectrum)// 循环遍历时,先调用GetEnumerator返回一个 ColorEnumberatorList 类型的枚举器 { Console.WriteLine(color); } } } 泛型接口和非泛型接口的区别: 泛型接口:IEnumerable<T>接口的GetEnumerator方法返回实现IEnumerator<T>的枚举器的实例;实现IEnumerator<T>的类实现了Current属性,它返回实际类型的对象,而不是object基类的引用。 非泛型接口:IEnumerable接口的GetEnumerator方法返回实现IEnumerator的枚举器的实例;实现IEnumerator的类实现了Current属性,它返回object的引用,然后我们必须把它转换为实际类型的对象。 4 迭代器 publicIEnumerator<string> BlackAndWhite() { yieldreturn"black"; yieldreturn"gray"; yieldreturn"white"; } 若在第一个yield return返回,则不执行后面的。 4.1 迭代器的常见使用模式有两种: (1)枚举器的迭代器模式 //IEnumerator的迭代器模式:使用迭代器来返回IEnumerator classMyClass1////实现了GetEnumerator方法的类就拥有枚举器,拥有枚举器就是可枚举类型 { publicIEnumerator<string> GetEnumerator() { return IteratorMethod();//直接调取使用迭代器生成枚举器的方法来返回枚举器 } privateIEnumerator<string> IteratorMethod()//迭代器这里是用来生成枚举器的 { yieldreturn"black"; yieldreturn"gray"; yieldreturn"white"; } } (2)可枚举类型的迭代器模式 //IEnumerable的迭代器模式:使用迭代器来返回IEnumerable classMyClass//实现了GetEnumerator方法的类就拥有枚举器,拥有枚举器就是可枚举类型 { publicIEnumerator<string> GetEnumerator() { IEnumerable<string> myEnumerable = BlackAndWhite();//要实现GetEnumerator方法先要获取一个 //可枚举类型然后返回其枚举器 return myEnumerable.GetEnumerator(); } public IEnumerable<string> BlackAndWhite()//迭代器这里就是用来产生可枚举类型的 { yieldreturn"black"; yieldreturn"gray"; yieldreturn"white"; } } 4.2 产生多个可枚举类型 classSpectrumD//有两个方法返回可枚举类型 SpectrumD类本身不是可枚举类型不能foreach 因为没实现GetEnumerator() { string[] colors = { "violet", "blue", "red", "yellow", "green","orange","black" }; publicIEnumerable<string> UVtoIR() { for (int i = 0; i < colors.Length; i++) { yieldreturn colors[i]; } } publicIEnumerable<string> IRtoUV() { for (int i = colors.Length-1; i >=0 ; i--) { yieldreturn colors[i]; } } } 4.3 将迭代器定义为属性 classSpectrumA { bool _ListFromUVtoIR; string[] colors = { "violet", "blue", "red", "yellow", "green", "orange", "black" }; public SpectrumA(bool listFromUVtoIR) { _ListFromUVtoIR = listFromUVtoIR; } publicIEnumerator<string> GetEnumerator()//实现SpectrumA为可枚举类型 根据bool变量返回枚举器 { return _ListFromUVtoIR ? UVtoIR : IRtoUV; } publicIEnumerator<string> UVtoIR //使用两个属性来返回两个不同的枚举器 { get { for (int i = 0; i < colors.Length; i++) { yieldreturn colors[i]; } } } publicIEnumerator<string> IRtoUV { get { for (int i = colors.Length - 1; i >= 0; i--) { yieldreturn colors[i]; } } } 4.4 迭代器实质:状态机
![](https://images2015.cnblogs.com/blog/328547/201706/328547-20170608161314481-136025390.png)