Ssssong += Dev

[유니티, C#] 반복자 패턴(Iterator Pattern), 코루틴 심화 본문

개발/공부

[유니티, C#] 반복자 패턴(Iterator Pattern), 코루틴 심화

ssong_dev 2022. 6. 23. 13:56

foreach : 어떤 형태든 정해진 순서대로 처리

IEnumeratable : 정해진 순서대로 반복 가능

IEnumerator : 정해진 순서대로 반복하는 도구

 

IEumerator에서 정해진 순서를 IEnumeratable에서 반복시키고, 그것을 foreach로 가져온다면

자동으로 지정한 순서대로 반복시켜준다.

 

 

IEnumerable은 이렇게 선언되어 있어 IEnumerator를 무조건 가지고 있다.

public interface IEnumerable
    {
        IEnumerator GetEnumerator();
    }

IEumerator의 기본 형태는 이렇다.

public interface IEnumerator
    {
        object Current { get; }

        bool MoveNext();
        void Reset();
    }

 

인터페이스 IEnumerable을 상속하여 반복 패턴을 만들고,

쓸 때는 안의 동작이 어떻게 되는 지 신경쓰지 않은 채 반복작업을 수행할 수 있다.

 

foreach로 가져올 수 있는 Stack, Queue, List 등은 이렇게 선언된 IEnumeratable이다.

순서가 지정되어 있기 때문에 foreach에서 그 순서대로 가져올 수 있는 것이다.

 

 

Stack 구조를 보면 IEnumerable을 상속받아 사용하고 있는 것을 볼 수 있다.

namespace System.Collections
{
    public class Stack : ICollection, IEnumerable, ICloneable
    {
        public Stack();
        public Stack(ICollection col);
        public Stack(int initialCapacity);

        public virtual int Count { get; }
        public virtual bool IsSynchronized { get; }
        public virtual object SyncRoot { get; }

        public static Stack Synchronized(Stack stack);
        public virtual void Clear();
        public virtual object Clone();
        public virtual bool Contains(object obj);
        public virtual void CopyTo(Array array, int index);
        public virtual IEnumerator GetEnumerator();
        public virtual object Peek();
        public virtual object Pop();
        public virtual void Push(object obj);
        public virtual object[] ToArray();
    }
}

 

 

CustomLinkedList라는 이름의 IEnumeratable을 만들어 보자.

CustomLinkedListEnumerator라는 이름의 IEnumerator를 가지고 있다.

public class Node
{
    public int data;
    public Node nextNode;
}

public class CustomLinkedListEnumerator : IEnumerator
{
    public Node head = null;
    public Node tail = null;
    public Node current = null;

    public object Current
    {
        get
        {
            return current.data;
        }
    }

    public bool MoveNext()
    {
        if(current == null)
        {
            current = head;
        }
        else
        {
            current = current.nextNode;
        }

        return current != null;
    }

    public void Reset()
    {
        current = head;
    }
}
public class CustomLinkedList : IEnumerable
{
    CustomLinkedListEnumerator enumerator = new CustomLinkedListEnumerator();

    public void AddBack(int data)
    {
        Node newNode = new Node();
        newNode.data = data;

        if(enumerator.head == null)
        {
            enumerator.head = newNode;
            enumerator.tail = newNode;
        }
        else
        {
            enumerator.tail.nextNode = newNode;
            enumerator.tail = newNode;
        }
    }

    public IEnumerator GetEnumerator()
    {
        return enumerator;
    }
}

 

이렇게 만들어진 CustomLinkedList를 foreach로 가져와 순서대로 처리할 수 있다.

private void Start()
    {
        CustomLinkedList customLinkedList = new CustomLinkedList();

        customLinkedList.AddBack(10);
        customLinkedList.AddBack(20);
        customLinkedList.AddBack(30);
        customLinkedList.AddBack(40);
        customLinkedList.AddBack(50);


        foreach (var item in customLinkedList)
        {
            Debug.Log(item);
        }
    }

 

 

 

 

 

 

코루틴 또한 반복자 패턴을 사용하고 있다. 반복하는 과정을 커스텀하는 게 가능하여

CustomYieldInstruction를 사용하여 IEnumerator 클래스를 커스텀한다.

//커스텀한 IEnumerator 클래스
public class CustomYieldReturn : CustomYieldInstruction
{
    public override bool keepWaiting
    {
        get
        {
            return !Input.GetKeyDown(KeyCode.Space);
        }
    }
}

public class Corutine : MonoBehaviour
{
    //IEnumerable은 정해진 순서대로 반복시킬 수 있는 도구(IEnumerator)를 가지고 있음
    //IEnumerator는 정해진 순서대로 반복시키는 도구
    IEnumerator CorutineTest()
    {
        //yield 은 어떠한 상태가 true가 될 때 까지 기다리는 역할을 한다.
        yield return new CustomYieldReturn();
    }
}

 

조금 더 자세하게는 이 분 포스팅이 좋더라!

c# 아니고 파이썬이지만 기본 원리는 비슷하다

https://bentist.tistory.com/88?category=1010744 

 

Iterator, Generator, Coroutine(코루틴)의 이해

파이썬에서 비동기 방식을 구현하기 위해서는 코루틴을 먼저 이해해야 한다. 그러나 코루틴의 저변에는 Iterator개념이 깔려 있기 때문에 Iterator와 Generator 객체를 함께 알아보고자 한다. 루틴(rout

bentist.tistory.com