C#图解教程(第四版)小笔记——枚举器和迭代器

枚举器

实现枚举器(enumerator)的对象称为可枚举类型(enumerable type 或enumerable)。
调用可枚举类型的GetEnumerator方法获取枚举器。
C#图解教程(第四版)小笔记——枚举器和迭代器_第1张图片
foreach原理:
①调用GetEnumerator方法获取enumerable的枚举器。
②从枚举器请求每一项并把它作为迭代变量,代码可以读取变量但是不能改变。

IEnumerator接口和IEnumerable接口

实现IEnumerator接口的枚举器包含三个函数成员:

  • Current
    只读属性,返回object类型的引用。
  • MoveNext
    把枚举器位置前进到集合的下一项。返回布尔值,只是新的位置是否有效,若有效返回true。
    枚举器的原始位置处于序列中的第一项前,所以MoveNext必须在第一次使用Current前调用。
  • Reset
    把位置重置为原始状态。

IEnumerable接口只有一个成员:GetEnumerator方法,返回对象的枚举器。
实现了IEnumerable接口的类称为可枚举类。

自定义一个可枚举类的方法

  • 自定义类MyEnumerator继承IEnumerator接口,作为枚举器
    实现Current,MoveNext、Reset方法。
  • 自定义类MyEnumerable继承IEnumerable接口
    实现GetEnumerator方法,获取枚举器(MyEnumerator)。

实际上,大多数情况下应该使用IEnumerableIEnumerator
IEnumerable< T>的GetEnumerator()返回实现IEnumerator< T>的枚举器类的实例。IEnumerator< T>的Current()返回具体类型而不是object。
非泛型接口的实现不是类型安全的(返回object需要转化为实际类型),而泛型接口的实现是类型安全的,它返回具体类型。

迭代器

System.Collections.Generic命名空间下,使用时需要using
C#从2.0版本开始提供迭代器。

  • yield return
    指定了序列中返回的下一项
  • yield break
    指定在序列中没有其他项

C#图解教程(第四版)小笔记——枚举器和迭代器_第2张图片

class MyClass
{
	public IEnumerator<string> GetEnumerator() { return BlackAndWhite();}
	//迭代器,返回一个枚举器,foreach操作MyClass类的对象会依次获得下面三个字符串
	public IEnumerator<string> BlackAndWhite()
	{
		yield return "black";
		yield return "gray";
		yield return "white";
	}
	//迭代器,返回一个可枚举类型,,foreach(string s in mc.AToB())依次获得两个字符串
	public IEnumerable<string> TBlackAndWhite()
	{
		yield return "black";
		yield return "gray";
		yield return "white";
	}
}

C#图解教程(第四版)小笔记——枚举器和迭代器_第3张图片
编译器生成的枚举器并不实现Reset()方法,调用时会抛出System.NotSupportedException异常。
在后台,由编译器生成的枚举器类是包含4个状态的状态机。

  • Before
    首次调用MoveNext的初始状态。
  • Running
    调用MoveNext后进入这个状态。在这个状态中,枚举器检测并设置下一项的位置,遇到yield return、yield break或迭代器体结束进时入下个状态。
  • Suspended
    状态机等待下次调用MoveNext的状态。
  • After
    没有更多项可以枚举。
    C#图解教程(第四版)小笔记——枚举器和迭代器_第4张图片

你可能感兴趣的:(C#小笔记,c#)