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 迭代器实质:状态机