枚举器enumerator

枚举器是一个只读的,作用于一序列值的、只能向前的游标。
枚举器是一个实现了下列任意一个接口的对象:

  1. System.Collections.IEnumerator
  2. System.Collections.IEnumerator<T>

技术上来说,任何一个含有名为MoveNext方法和名为Current的属性的对象,都会被当做枚举器来对待。
foreach语句会迭代可枚举的对象(enumerable object)。可枚举的对象是一序列值的逻辑表示。它本身不是游标,它是一个可以基于本身产生游标的对象。

可枚举对象enumerator object

一个可枚举对象可以使(下列任意一个):
实现了IEnumerable或者IEnumerable的对象。
有一个名为GetEnumerator的方法,并且该方法返回一个枚举器(enumerator)
IEnumerator和IEnumerable是定义在System.Collections命名空间下的。
IEnumerator和IEnumerable是定义在System.Collections.Generic命名空间下的。

枚举模式 enumeration pattern

未命名图片.png
例子
未命名图片.png
注意:如果枚举器(enumerator)实现了IDisposable接口,那么foreach语句就会像using语句那样,隐式的dispose掉这个enumerator对象。

集合初始化器

你可以只用一步就把可枚举进行实例化并填充里面的元素:

  1. using System.Collections.Generic;
  2. ..
  3. List<int> list = new List<int>{1,2,3};

但是编译器会把它翻译成:

  1. using System.Collections.Generic;
  2. ..
  3. List<int> list = new List<int>();
  4. list.Add(1);
  5. list.Add(2);
  6. list.Add(3);

上例中。要求可枚举对象实现了System.Collections.IEnumerable接口,并且他还有一个可接受适当参数的Add方法。
例子
未命名图片.png

迭代器iterators

foreach语句是枚举器(enmerator)的消费者,而迭代器(iteraotr)是枚举器的生产者。
例子
未命名图片.png
yieid return语句表达的意思是:这是你向我请求从枚举器产生的下一个元素。
没逢遇到yield语句,控制权都会回到调用者哪里,但是被调用这的状态还是会保持的,这样的话可以保证当调用者列举出下一个元素的时候,方法可以继续执行。
这个状态的声明周期被绑定到了枚举器上,这样的话,当调用者完成枚举动作之后,状态可以被释放。

原理解释

编译器把迭代方法转换成私有的,实现了IEnumerable和/或IEnumerator的类。
迭代器内部的逻辑被反转并且被切分到编译器生成的枚举器类里面的MoveNext方法和Current属性里。
这意味着当你调用迭代器方法时,你所做的时机就是对编译器生成的类进行实例化;运行的代码里没有一行是你写的。。。
你写的代码仅会对结果序列进行枚举的时候才会运行,例如使用foreach语句。

迭代器的语义

未命名图片.png

多个yield语句

方法可以含有多个yieid语句
未命名图片.png

yield break

yield break语句表示迭代器块会提前退出,不在返回更多的元素。
未命名图片.png
return语句在迭代器块里面是违法的,你必须使用yield break代替。

迭代器和try/catch/finally块

yield return语句保护可以出现在含有catch子句的try块开面:
未命名图片.png
yield return 也不能出现在catch或者finally块里面。
但是yield return可以出现在只含有finally块的try块里面:
未命名图片.png
当消费的枚举器到达序列终点或被disposed的时候,finally块里面的代码会执行
如果你提前进行了break那么foreach语句也会dispose掉枚举器,所以用起来很安全。
当显式的使用枚举器的时候,通常会犯这样一个错误:没有dispose掉枚举就不再用它了,这就绕开了finally块。针对这种情况,你可以使用using语句来规避风险:
未命名图片.png

组合序列

迭代器是高度可组合的
未命名图片.png
上例中的每个元素直到最后时刻才会被计算,就也就是被MoveNext()操作请求的时候。
未命名图片.png