C#중협정의 원리

9387 단어 unity
얼마 전에 유닛 스크립트 프로그래밍을 봤는데 유닛에서 협정의 실현 원리를 설명했고 이해하기 어려웠다.나는 총결산을 해서 기초적인 것을 주었다.
일단은 c#에서 이엘드 키워드.
Iield 키워드가 컴파일러에 있는 방법을 표시하는 방법은 교체 블록입니다.컴파일러는 반복 블록에 표시된 행동을 실현하기 위해 클래스를 생성합니다.교체기 블록에서 yield 키워드와return 키워드를 결합하여 사용하여 매거진 대상에게 값을 제공합니다.이것은foreach 문장의 순환마다 되돌아오는 값입니다.ield 키워드는break와 결합하여 사용할 수 있으며 교체가 끝났다는 것을 나타냅니다.msdn
msdn이 말한 것은 약간 추상적입니다. 다음은 코드를 보십시오
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace YieldTest
{
    class Program
    {
        static void Main(string[] args)
        {
            foreach (int i in Feige.Fei())
            {
                Console.WriteLine("      :" + i );
            }
        }
        class Feige
        {
            public static IEnumerable<int> Fei()
            {
                for (int i = 0; i < 10; i++)
                {
                    yield return i;
                    Thread.Sleep(1000);
                }
            }
        }
    }
}

결과: 반환 결과: 0 반환 결과: 1 반환 결과: 2 반환 결과: 3 반환 결과: 4 반환 결과: 5 반환 결과: 6 반환 결과: 7 반환 결과: 8 반환 결과: 9
다음은 이런 실현 방식도 마찬가지다.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace YieldTest
{
    class Program
    {
        static void Main(string[] args)
        {
            IEnumerator i = Feige.Fei();

            while (i.MoveNext())
            {
                Console.WriteLine(i.Current);
                Thread.Sleep(500);
            }
            Console.ReadLine();
        }
        class Feige
        {
            public static IEnumerator<int> Fei()
            {
                for (int i = 0; i < 10; i++)
                {
                    yield return i;
                }
            }
        }
    }
}

아날로그 프로토콜의 실현 코드
using System.Collections;
using System.Collections.Generic;

namespace Com.Coroutine
{

    public class Coroutine
    {

        internal IEnumerator m_Routine;

        internal IEnumerator Routine
        {
            get { return m_Routine; }
        }

        internal Coroutine()
        {
        }

        internal Coroutine(IEnumerator routine)
        {
            this.m_Routine = routine;
        }

        internal bool MoveNext()
        {

            var routine = m_Routine.Current as Coroutine;

            if (routine != null)
            {
                if (routine.MoveNext())
                {
                    return true;
                }
                else if (m_Routine.MoveNext())
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else if (m_Routine.MoveNext())
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }

    // use this as a template for functions like WaitForSeconds()
    public class WaitForCount : Coroutine
    {
        int count = 0;
        public WaitForCount(int count)
        {
            this.count = count;
            this.m_Routine = Count();
        }

        IEnumerator Count()
        {
            while (--count >= 0)
            {
                System.Console.WriteLine(count);
                yield return true;
            }
        }
    }

    // use this as the base class for enabled coroutines
    public class CoroutineManager
    {

        internal List m_Coroutines = new List();

        // just like Unity's MonoBehaviour.StartCoroutine
        public Coroutine StartCoroutine(IEnumerator routine)
        {
            var coroutine = new Coroutine(routine);
            m_Coroutines.Add(coroutine);
            return coroutine;
        }

        // call this every frame
        public void ProcessCoroutines()
        {
            for (int i = 0; i < m_Coroutines.Count; )
            {
                var coroutine = m_Coroutines[i];
                if (coroutine.MoveNext())
                {
                    ++i;
                }
                else if (m_Coroutines.Count > 1)
                {
                    m_Coroutines[i] = m_Coroutines[m_Coroutines.Count - 1];
                    m_Coroutines.RemoveAt(m_Coroutines.Count - 1);
                }
                else
                {
                    m_Coroutines.Clear();
                    break;
                }
            }
        }
    }
}

참고 자료
C# yield 키워드 사용

좋은 웹페이지 즐겨찾기