2020-02-04【c#】协程与迭代器_自定义协程计时器

2020-02-04  本文已影响0人  持刀的要迟到了

今天看到一个用法,yield return <一个对象>。它不是等待这个对象不为空;经过询问及查询,这个对象其实是一个迭代器对象(协程也是一个迭代器)。
其实说迭代器什么的有点抽象,其实就是继承并实现了两个接口。
以下是自定义协程计时器。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace TestSpace
{

    public class CoroutineTest : MonoBehaviour
    {
        TestNode[] nds;
        TestNode nd1 = new TestNode(1, 2f);
        TestNode nd2 = new TestNode(2, 2f);
        TestNode nd3 = new TestNode(3, 2f);
        TestNode nd4 = new TestNode(4, 2f);

        // Start is called before the first frame update
        void Start()
        {
            nds = new TestNode[4] { nd1, nd2, nd3, nd4 };
            StartCoroutine(Test());
        }


        private IEnumerator Test()
        {
            for(int i = 0;i < nds.Length;i ++)
            {
                Debug.Log(nds[i].nodeId);
                yield return nds[i];
            }
        }

    }



    public class TestNode : IEnumerable<TestNode>, IEnumerator
    {
        public int nodeId;
        public float waitTime;

        public TestNode(int nodeid, float waittime)
        {
            nodeId = nodeid;
            waitTime = waittime;
        }


        public IEnumerator<TestNode> GetEnumerator()
        {
            Debug.LogError("GetEnumerator1");
            yield break;
        }
        IEnumerator IEnumerable.GetEnumerator()
        {
            Debug.LogError("GetEnumerator0");
            return GetEnumerator();
        }


        bool init = false;
        float endtime = -1f;


        private bool IsTimeOver()
        {
            if(!init)
            {
                init = true;
                endtime = Time.time + waitTime;
            }

            if(Time.time >= endtime)
            {
                Debug.Log("Time Up " + nodeId);
                Reset();
                return false;
            }
            else
            {
                return true;
            }
        }


        public object Current { get { /*Debug.LogError("GetCurrent");*/ return null; } }

        public bool MoveNext()
        {
            return IsTimeOver();
        }

        public void Reset()
        {
            Debug.LogError("Reset");

            init = false;
            endtime = -1f;
        }

    }
}

c#迭代器代码讲解
详解C# 迭代器

由第一篇文章可知,迭代器是有两个接口,IEnumerableIEnumerator。这俩玩意,继承第一个,需要实现GetIEnumerator方法,来获得IEnumerator元素。而IEnumerator要实现获得当前、移到下一个、重置,三个方法;它就是迭代器!

image.png
运行了一下文章中此处的例子,断点调试发现,每次都需要MoveNext函数执行后,才会执行一次IEnumerable中内容,执行到return后返回,完成改次迭代。然后返回值会传入迭代器的Current内部。
image.png
秋雨总结
上一篇下一篇

猜你喜欢

热点阅读