C#笔记进阶篇05 迭代器
——本系列是基于人民邮电出版社《C#2008 C#图解教程》、清华大学出版社《C#入门经典(第五版)》两本书的自学C#笔记,如果您发现了本文的纰漏,还望不吝指正。
写在前边
迭代器的定义是,它是一个代码块,按顺序提供了要在foreach 循环中使用的所有值。一般情况下,这个代码块是一个方法,但也可以使用属性访问器和其他代码作为为迭代器。 ——清华大学出版社《C#入门经典(第五版)》
System.Collections 名称空间中的几个接口:
- ICollection(继承于IEnumerable)可以获取集合中项的个数,并能把项复制到一个简单的数
组类型中。 - IEnumerator 枚举数接口,可以迭代一个类
- IEnumerable 枚举接口,可以迭代集合中的项,负责使用foreach 循环
1. IEnumerator接口
如果要迭代一个类,可使用方法GetEnumerator(),其返回类型是IEnumerator 枚举数接口
如上图所示,IEnumerator接口包含三个函数成员:Current、MoveNext以及Reset
1.1 IEnumerator接口的三个函数成员
1).Current
- 返回序列中当前位置项的属性。
- 它是只读属性。
- 它返回object类型的引用,所以可以返回任何类型。
2).MoveNext
- 把枚举数位置前进到集合中下一项的方法。它返回布尔值,指示新的位置是有效位置或已经超过了序列的尾部
- 如果新的位置是有效的,方法返回true。
- 如果新的位置是无效的(比如到达了尾部),方法返回false。
- 枚举数的原始位置在序列中的第一项之前。MoveNext必须在第一次使用Current之前使用,否则CLR会抛出一个InvalidOperationException异常。
3).Reset
- 把位置重置为原始状态。
- 该位置位于集合中第一个元素之前
1.2 声明IEnumerator 的枚举数
class MyEnumerator : IEnumerator
{
public object Current
{
get
{
throw new NotImplementedException();
}
}
public bool MoveNext()
{
throw new NotImplementedException();
}
public void Reset()
{
throw new NotImplementedException();
}
}
例如,下面代码实现了一个列出颜色名数组的枚举数类:
class ColorEnumerator : IEnumerator
{
string[] Colors;
int Position = -1;
public object Current
{
get
{
return Colors[Position];
}
}
public bool MoveNext()
{
if (Position < Colors.Length - 1)
{
Position++;
return true;
}
else
{
return false;
}
}
public void Reset()
{
Position = -1;
}
//构造函数
public ColorEnumerator(string[] theColors)
{
Colors = new string[theColors.Length];
for (int i = 0; i < theColors.Length; i++)
{
Colors[i] = theColors[i];
}
}
}
//源码来自 人民邮电出版社《C#2008 C#图解教程》 第20章
2. IEnumerable接口
如果要迭代一个类成员,例如一个方法,则使用IEnumerable 枚举接口
如上图所示,IEnumerable接口只有一个成员——GetEnumerator方法,它返回对象的IEnumerator 枚举数。
2.1 yield return语句
在迭代器块中,使用yield return选择要在foreach循环中使用的值,而实际返回的是object类型的值
例:如下代码中,SimpleList()就是迭代器,它是一个方法,所以使用IEnumerable返回类型
public static IEnumerable SimpleList()
{
//yield return为使用它的foreach块提供了3个值
yield return "string 1";
yield return "string 2";
yield return "string 3";
}
static void Main(string[] args)
{
foreach (string item in SimpleList())
Console.WriteLine(item);
Console.ReadKey();
}
//源码来自 清华大学出版社《C#入门经典(第五版)》 第11章
控制台输出结果:
string 1
string 2
string 3
2.2 声明IEnumerable 的枚举
class MyClass : IEnumerable
{
public IEnumerator GetEnumerator()
{
throw new NotImplementedException();
}
}
如下的代码给出了一个使用之前示例中的ColorEnumerator枚举数类的示例。要知道,ColorEnumerator实现了IEnumerator
class MyColors : IEnumerable
{
string[] Colors = { "Red", "Yellow", "Blue" };
public IEnumerator GetEnumerator()
{
//枚举数类的实例
return new ColorEnumerator(Colors);
}
}
把MyColors和ColorEnumerator示例放在一起,主函数中创建MyColors的实例,并在foreach中使用。
static void Main()
{
MyColors mc = new MyColors();
foreach (string color in mc)
{
Console.WriteLine("{0}",color);
}
}
//源码来自 人民邮电出版社《C#2008 C#图解教程》 第20章
控制台输出结果:
Red
Yellow
Blue