目录
枚举器和可枚举类型
IEnumerator 接口
IEnumerable 接口
实现 IEnumerable 和 IEnumerator的示例
泛型枚举接口
迭代器
迭代器块
使用迭代器来创建枚举器
使用迭代器来创建可枚举类型
常见迭代器模式
产生多个可枚举类型
将迭代器作为属性
迭代器实质
枚举器和可枚举类型
数组按需提供一个叫做枚举器的对象。枚举器可以依次返回请求数组中的元素。
调用对象的GetEnumerator 方法可以获取一个对象枚举器,可以知道枚举器的类型。实现GetEnumerator方法的类型叫做 可枚举类型。数组是可枚举数组
foreach 结构设计用来和可枚举类型一起使用。只要它遍历的对象是可枚举类型,就可以执行如下操作:
IEnumerator 接口
实现了 IEnumerator 接口的枚举器包含3个函数成员:Current ,MoveNext, Reset
枚举器与序列中的当前项保持联系的方式完全取决于实现,可以通过对象引用,索引值或其他方式来实现
IEnumerable 接口
可枚举类型是指实现了 IEnumerable 接口的类。IEnumerable 接口只有一个成员---GetEnumerator方法,它返回对象的枚举器
实现 IEnumerable 和 IEnumerator的示例
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
namespace Csharpzuoye
{
class ColorEnumerator : IEnumerator
{
string[] _colors;
int _position = -1;
public ColorEnumerator(string[] theColors) //构造函数
{
_colors = new string[theColors.Length];
for (int i = 0; i < theColors.Length; i++)
_colors[i] = theColors[i];
}
public object Current //实现Current
{
get
{
if (_position == -1)
throw new InvalidOperationException();
if (_position >= _colors.Length)
throw new InvalidOperationException();
return _colors[_position];
}
}
public bool MoveNext() //实现MoveNext
{
if(_position < _colors.Length - 1)
{
_position++;
return true;
}
else
{
return false;
}
}
public void Reset()
{
_position = -1;
}
}
class Spectrum : IEnumerable
{
string[] Colors = { "violet", "blue", "cyan", "green", "yellow", "orange", "red" };
public IEnumerator GetEnumerator()
{
return new ColorEnumerator(Colors);
}
}
class Program
{
static void Main()
{
Spectrum spectrum = new Spectrum();
foreach (string color in spectrum)
Console.WriteLine(color);
}
}
}
泛型枚举接口
IEnumerable<T> 和 IEnumerator<T> 泛型
泛型与非泛型的差别:
非泛型接口的实现不是类型安全的,它们返回object 类型的引用,然后必须转化为实际类型。
而泛型接口的枚举器是类型安全的,它返回实际类型的引用。如果创建自己的可枚举类,应该实现这些泛型接口
迭代器
我们可以把手动编码的可枚举类型和枚举器替换为有迭代器生成的可枚举类型和枚举器
迭代器块
迭代器块是有一个或多个 yield' 语句的代码块。下面三种任意一种都可以是迭代器块
迭代器块与其他代码块不同。其他块包含的语句被当作是命令式的,需要先执行代码块的第一个语句,然后执行后面的语句,最后离开块。
迭代器块不是需要在同一时间执行的一串命令式命令,而是描述了希望编译器为我们创建的枚举器类的行为。
编译器得到有关如何枚举项的描述后,使用它来构建包含所有需要的方法和属性实现的枚举器类。结果类被嵌套包含在迭代器声明的类中
使用迭代器来创建枚举器
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
namespace Csharpzuoye
{
class MyClass
{
public IEnumerator<string> GetEnumerator()
{
return BlackAndWhite(); //返回枚举器
}
//返回枚举器
public IEnumerator<string> BlackAndWhite() //迭代器
{
yield return "black";
yield return "gray";
yield return "white";
}
}
class Program
{
static void Main()
{
MyClass mc = new MyClass();
foreach (string shade in mc) //使用MyClass的实例
Console.WriteLine(shade);
}
}
}
使用迭代器来创建可枚举类型
在本节中我们使用迭代器来创建可枚举类型,而不是枚举器
图中左边的迭代器代码演示了它的返回类型是IEnumerable<string>
图中右边演示了他有一个嵌套类实现了IEnumerator<string> 和 IEnumerator<string>
常见迭代器模式
产生多个可枚举类型
将迭代器作为属性
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
namespace Csharpzuoye
{
class Spectrum
{
bool _listFromUVtoIR;
string[] colors = { "violet", "blue", "cyan", "green", "yellow", "orange", "red" };
public Spectrum(bool listFromUVtoIR)
{
_listFromUVtoIR = listFromUVtoIR;
}
public IEnumerator<string> GetEnumerator()
{
return _listFromUVtoIR ? UVtoIR : IRtoUV;
}
public IEnumerator<string> UVtoIR
{
get
{
for (int i = 0; i < colors.Length; i++)
yield return colors[i];
}
}
public IEnumerator<string> IRtoUV
{
get
{
for (int i = colors.Length - 1; i >= 0; i--)
yield return colors[i];
}
}
}
class Program
{
static void Main()
{
Spectrum startUV = new Spectrum(true);
Spectrum startIR = new Spectrum(false);
foreach (string color in startUV)
Console.Write("{0} ", color);
Console.WriteLine();
foreach (string color in startIR)
Console.Write("{0} ", color);
Console.WriteLine();
}
}
}
迭代器实质