概念

  • 迭代器(iterator) 有时又称光标(cursor)是一种程序设计的软件设计模式
  • 迭代器模式提供一个方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的标识
  • 在表现效果上看是可以在容器对象(例如链表或数组)上遍历访问的接口
  • 设计人员无需关心容器对象的内存分配的实现细节
  • 可以用foreach遍历的类,都是实现了迭代器的
  • 关键接口:IEnumerator IEnumerable
  • 命名空间:using System.Collections;
  • 需要同时继承IEnumerator和IEnumerable接口来实现其中的方法
  • 迭代器在unity中的其中一个重要用途就是协程,可参考这个文章

迭代器的实现

标准迭代器

  • foreach迭代的本质:
    • 先执行in后面的对象的IEnumerable实现的GetIEnumerator方法
    • 然后执行继承IEnumerator得到的MoveNext方法
    • 只要MoveNext方法的返回值为true,就会得到Current对象并赋值给foreach中的item
class CustomList : IEnumerable, IEnumerator
{
    private int[] list;
    private int index = -1;
    public CustomList() 
    { 
        list = new int[] 
        {
            1, 2, 3, 4, 5, 6, 7, 8 
        }; 
    }
    public CustomList(params int[] list)
    {
        this.list = list;
    }
    public IEnumerator GetEnumerator()
    { 
        Reset();
        return this; 
    }
    public object Current
    {
        get
        {
            return list[index]; 
        } 
    }
    public bool MoveNext()
    {
        index++;
        return index < list.Length;
    }
    public void Reset()
    {
        index = -1;
    }
}
class Program
{
    static void Main(string[] args)
    {
        CustomList list = new CustomList();
        foreach (int item in list)
        {
            Console.WriteLine(item);
        }
        Console.ReadKey();
    }
}

用yield return语法糖实现迭代器

  • yield return 是C#提供给我们的语法糖
  • 所谓语法糖,也称糖衣语法,主要作用就是将复杂逻辑简单化,可以增加程序的可读性,从而减少程序代码出错的机会|
  • 关键接口: IEnumerable
  • 让想要通过foreach遍历的自定义类实现接口中的方法GetEnumerator即可
class CustomList2 : IEnumerable
{
    private int[] list;
    public CustomList2(params int[] list) 
    { 
        this.list = list;
    }
    public IEnumerator GetEnumerator()
    {
  
        for (int i = 0; i < list.Length; i++)
        {
            //yield关键字配合迭代器使用
            //可以理解为暂时返回保留当前的状态
            yield return list[i];
        }
    }
}

用yield return语法糖为泛型类实现迭代器

class CustomList<T> : IEnumerable
{
    private 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];
        }
    }
}

参考资料

https://www.bilibili.com/video/BV1Ar4y1K7AK?p=24