C#中的迭代器

5 篇文章 0 订阅
1.迭代器模式

  迭代器模式指按照一定顺序来访问一个集合对象中的每个元素, 但是同时不会暴露集合对象的内部结构. C#中内置的迭代器模式就是Foreach语句, 它可以顺序遍历容器中的每个元素. 而迭代器的具体实现主要是靠IEnumerable 和IEnumerator.

2. IEnumerator

  IEnumerator接口其实就是foreach的具体实现, 它只定义了三个函数, 如下

	public interface IEnumerator
	{
	  bool MoveNext();
	
	  object Current { get; }
	
	  void Reset();
	}

  也就是说我们实现一个最简单的IEnumerator接口只需要实现这三个函数即可. MoveNext()表示向集合中的下一个元素移动, 如果有下一个元素返回true, 没有就返回false. Current是一个只读属性, 返回当前迭代器所指元素. Reset()表示重置迭代器到第一个元素.

	class MyIEnumerator: IEnumerator
    {
        private int count = 10;
        public bool MoveNext()
        {
            --count;
            return count >= 0;
        }

        public object Current
        {
            get { return count; }
        }

        public void Reset()
        {
            count = 10;
        }
    }

  这就是一个简单的IEnumerator, 如果用Foreach输出, 可以得到从9到0的十个计数. 而具体的实现过程还需要IEnumerable.

3. IEnumerable

  IEnumerable可以粗略的理解为可迭代(遍历)的, 如果接口继承了IEnumerable, 那么就可以使用Foreach语句进行迭代操作. 这个接口只定义了一个函数, 如下:

	public interface IEnumerable
	{
	  IEnumerator GetEnumerator();
	}

  这个函数需要返回一个我们刚才定义的IEnumerator, 即告知上层调用方可以枚举.

	class MyIEnumerable : IEnumerable
    {
        public IEnumerator GetEnumerator()
        {
            return new MyIEnumerator();
        }
    }

  这个时候我们的迭代器已经实现, 可以使用Foreach语句进行迭代操作.

	void Start()
    {
        foreach (var VARIABLE in new MyIEnumerable())
        {
            Debug.Log(VARIABLE);
        }
    }

  此时运行程序, 可以得到我们想要的结果, 从9数到0, 共计10个数.
在这里插入图片描述
  我们现在有一个完整的迭代器了, 但是有一个问题, 很多时候我们需要的迭代器并不复杂, 如上面的计数装置, 如果每次都需要实现IEnumerator和IEnumerable十分不方便, 显得头重脚轻, 这时我们可以使用yield.

4.yield

  yield是为了方便使用迭代器而产生的语法糖, 他可以直接使用在返回类型为IEnumerable或IEnumerator的函数中直接实现迭代器操作. 它有两种用法yield break 和yield return (something) 效果和break与return一样. 当使用yield return在foreach语句中进行迭代器操作时, 每一次执行到yield return时都会返回后面定义的something并且记录函数内的信息, 下一次运行时继续.

	void Start()
    {
        foreach (var VARIABLE in myIEnumerable())
        {
            Debug.Log(VARIABLE);
        }
    }

    private IEnumerable myIEnumerable()
    {
        for (int i = 9; i >= 0; --i)
        {
            if (i == 5) yield break;
            yield return i;
        }
    }

  这里我们在i = 5的时候使用了yield break终止了迭代器操作, 如果去掉它, 这个函数就和我们刚才定义的迭代器作用一样, 产生了9到0, 共10个数的倒数.

5. 协程(coroutine)

  除了foreach语句, Unity中另一种迭代器模式就是协程, 它是根据每一次IEnumerator的MoveNext()方法调用进行迭代的, 有些类似于Unity的Update方法. 同时它可以结合Unity的yield return new WaitForSeconds(time)等等接口实行迭代器+定时器模式.
使用和停止协程比较简单, 都只要传入IEnumerator就可以.

    public Coroutine StartCoroutine(IEnumerator routine)
    public void StopCoroutine(IEnumerator routine)

  使用协程的方法实现我们的从9数到0.

	void Start()
	{
	    StartCoroutine(myCoroutine());
	}
	
	private IEnumerator myCoroutine()
	{
	    for (int i = 9; i >= 0; i--)
	    {
	        Debug.Log(i);
	        yield return new WaitForSeconds(1f);
	    }
	
	    yield return StartCoroutine(myCoroutine());
	}

  值得注意的是unity里有很多可以和yield结合使用的语句块, 如上的代码不仅实现了从9数到0, 还实现了每隔1秒数一次, 数到0后继续从头开始数, 当然还有很多其他有趣的功能可以通过coroutine和yield实现.

  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值