迭代器详解
迭代器模式
定义
迭代器提供了一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部结构。
结构
迭代器由四部分组成:
- Iterator:定义访问和遍历元素的接口。
- ConcreteIterator:实现迭代器接口;遍历时跟踪当前位置。
- Aggregate:定义创建相应迭代器对象的接口。
- ConCreteAggregate:实现创建Aggregate中定义的接口。
适用场景
- 系统需要访问一个聚合对象的内容而无需暴露它的内部表示
- 系统需要支持对聚合对象的多种遍历
- 系统需要为不同的聚合结构提供一个统一的接口
实现一个简单的迭代器
下边是一个简单的Iterator的实现
class ListIterator<T> : IEnumerator<T> { List<T> list; int current; public ListIterator(List<T> list) { this.list = list; current = -1; } public T Current { get { return list[current]; } } public bool MoveNext() { return ++current < list.Count; } public void Reset() { current = -1; } }
虽然我们不能修改list本身,但是我们可以使用ListIterable<T>封装一个list:
1 class ListIterator<T> : IEnumerator<T> 2 { 3 List<T> list; 4 int current; 5 6 public ListIterator(List<T> list) 7 { 8 this.list = list; 9 current = -1; 10 } 11 12 public T Current { get { return list[current]; } } 13 14 public bool MoveNext() 15 { 16 return ++current < list.Count; 17 } 18 19 public void Reset() 20 { 21 current = -1; 22 } 23 24 }
最后我们可以写一个返回Ienumerable<T>类型的GetElements方法
static IEnumerable<T> GetElements<T>(this List<T> list) { return new ListIterable<T>(list); }
C#中的迭代器
在.NET中迭代器模式的Iterator和Aggregate已经存在了,其中IEnumerator接口就是Iterator,而IEnumerable就是Aggregate。不仅如此,在.NET2.0之后的版本中,我们可以使用yield关键字方便的实现迭代器模式。
例如上边GetElements方法的代码可以写成:
static IEnumerable<T> GetElements<T>(List<T> list) { for (int i = 0; i < list.Count; i++) { yield return list[i]; } }