C#迭代器

迭代器

只有实现了IEnumerable的类(可枚举类型)才可以使用foreach进行遍历;

Array、ArrayList、List等属于可枚举类型;

IEnumerable[可枚举类型接口]

IEnumerator[枚举类型接口]

只要一个类继承了可枚举类型接口,并且实现了可枚举类型接口中的成员,那么这个类叫做可枚举类型。

public interface IEnumerable
{
    IEnumerator GetEnumerator();
}
public interface IEnumerator
{
    object Current { get; }

    bool MoveNext();

    void Reset();
}

Current: 只读的属性,返回的是objecj类型的引用,第一次位置为-1

MoveNext: 把枚举器位置 移动到下一项 bool表示 新位置是否有效

Reset: 把位置重置到初始状态

案例

使用枚举器的方式遍历数组

private void Start()
{
    int[] array = { 10, -90, 1, 2, 3, 4, 5, 6 };
    IEnumerator ie = array.GetEnumerator();
    while (ie.MoveNext()) 
    {
        int x = (int)ie.Current;
        print(x);
    }
}

自定义一个迭代器

public class Test : MonoBehaviour
{
    private void Start()
    {

        // 迭代器
        object[] datas = { true, 100, 19, false, 'd', "df" };
        MyIEnumerable me = new MyIEnumerable(datas);
        foreach (object o in me)
        {
            print(o);
        }
    }
}

/// <summary>
/// 自定义的可枚举类型
/// </summary>
public class MyIEnumerable : IEnumerable
{
    public object[] Values;

    public MyIEnumerable(object[] values)
    {
        Values = values;
    }

    public IEnumerator GetEnumerator()
    {
        return new MyIEnumerator(this);
    }
}

public class MyIEnumerator : IEnumerator
{
    private int _position;

    private MyIEnumerable _data;

    public bool MoveNext()
    {
        if (_position != _data.Values.Length)
            _position++;
        return _position < _data.Values.Length;
    }

    public MyIEnumerator(MyIEnumerable mie)
    {
        _data = mie;
        _position = -1;
    }

    public void Reset()
    {
        _position = -1;
    }

    public object Current
    {
        get
        {
            if (_position == -1 || _position == _data.Values.Length)
            {
                return null;
            }

            return _data.Values[_position];
        }
    }
}

更简单自定义的迭代器

public class Test : MonoBehaviour
{
    private void Start()
    {
       
        MyIEnumerable me = new MyIEnumerable();
        foreach (int i in me)
        {
            print(i);
        }
    }
}

public class MyIEnumerable 
{
    public IEnumerator<int> GetEnumerator()
    {
        yield return 100;
        yield return 200;
        yield return 300;
        yield return 400;
        yield return 500;
    }
}

yield return 详解

可以根据返回值类型,告诉编辑器 创建可枚举类型 or 枚举器类型,指定了枚举器 对象下一个可枚举项

迭代器的执行顺序

当创建完一个可枚举类型(不管是手动实现 还是迭代器 创建)

枚举器 实际上可以看成是四种状态的状态机

Before 首次调用MoveNext之前的状态

初始位置在第一个可枚举之前

Running状态下,枚举器 检测下一项的位置

当遇到yield return 时 会进入 挂起状态, 知道遇到下一个 MoveNext()

当遇到yield break 时 或 迭代器主题结束,会进入退出状态

Suspended挂起状态

等待下一次MoveNext调用时 继续唤醒

After 已经到最后的位置,没有可枚举项

上一篇
下一篇