(一)迭代器是什么
迭代器(iterator)有时又称光标(cursor),是程序设计的软件设计模式
迭代器模式提供一个方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的标识
在表现效果上看,是可以在容器对象(例如链表或数组)上遍历访问的接口
设计人员无需关心容器对象的内存分配的实现细节,可以用 foreach 遍历的类,都是实现了迭代器的
(二)标准迭代器实现
// 关键接口:IEnumerator,IEnumerable
// 命名空间:using System.Collections;
// 可以通过同时继承IEnumerable和IEnumerator实现其中的方法
internal class CustomList : IEnumerable, IEnumerator
{
private readonly int[] list;
// 从-1开始的光标 用于表示 数据得到了哪个位置
private int position = -1;
public CustomList() {
list = new[] { 1, 2, 3, 4, 5, 6, 7, 8 };
}
// IEnumerable
public IEnumerator GetEnumerator() {
Reset();
return this;
}
public object Current => list[position];
public bool MoveNext() {
// 移动光标
++position;
// 是否溢出 溢出就不合法
return position < list.Length;
}
// reset是重置光标位置 一般写在获取 IEnumerator对象这个函数中
// 用于第一次重置光标位置
public void Reset() {
position = -1;
}
}
// foreach本质
// 1.先获取in后面这个对象的 IEnumerator
// 会调用对象其中的GetEnumerator方法 来获取
// 2.执行得到这个IEnumerator对象中的 MoveNext方法
// 3.只要MoveNext方法的返回值时true 就会去得到Current
// 然后复制给 item
foreach (int item in list) Console.WriteLine(item);
(三)yield return 语法糖实现迭代器
yield return 是 C# 提供给我们的语法糖
所谓语法糖,也称糖衣语法
主要作用就是将复杂逻辑简单化,可以增加程序的可读性
从而减少程序代码出错的机会
// 关键接口:IEnumerable
// 命名空间:using System.Collections;
// 让想要通过foreach遍历的自定义类实现接口中的方法GetEnumerator即可
internal class CustomList2 : IEnumerable
{
private readonly int[] list;
public CustomList2() {
list = new[] { 1, 2, 3, 4, 5, 6, 7, 8 };
}
public IEnumerator GetEnumerator() {
for (int i = 0; i < list.Length; i++)
// yield关键字 配合迭代器使用
// 可以理解为 暂时返回 保留当前的状态
// 一会还会在回来
// C#的语法糖
yield return list[i];
}
}
(四)yield return 语法糖实现泛型迭代器
internal class CustomList<T> : IEnumerable
{
private readonly T[] array;
public CustomList(params T[] array) {
this.array = array;
}
public IEnumerator GetEnumerator() {
for (int i = 0; i < array.Length; i++) yield return array[i];
}
}
迭代器就是可以让我们在外部直接通过 foreach 遍历对象中元素而不需要了解其结构
主要的两种方式
- 传统方式继承两个接口,实现里面的方法
- 用语法糖 yield return 去返回内容,只需要继承一个接口即可