Unity. IEnumrator 부터 Coroutine 까지

PAVDUP·2023년 2월 26일
0

예전 Coroutine 에 대해 자세히 알아본 내용을 정리한다.

Coroutine은 IEnumerator 의 반환 타입을 가지고, 함수 Body 에 yield return 문을 포함한 함수이다.

그냥 일반 함수처럼 (반환 형태 void 인 애들처럼) 호출하는 것 또한 가능하다!

그럼, Coroutine을 IEnumerator 와 yield return 이 기능함으로써 만들어진다는 것인데, 이것이 무엇일까?

IEnumerator, IEnumerable, Foreach

IEnumerator (I Enum er ator)

Class 내부의 Collection을 반복할 수 있도록 지원한다.

Collection : object (객체)를 group으로 관리하는 방법. Array, Collection 두 가지가 존재한다.

위의 설명으로는 부족한 점이 있을 것 같아 추가 서술 :
IEnumerator interface 를 구현한 Class의 경우, 그 내부 구성요소는

  • Collection (어떤 타입에 관한 Group - List 일 수도, Array 일 수도 있다.)
  • Index : int 형 변수. 어떤 지점인지를 나타내는 정수값.
  • 아래에 서술된 Method 들 : 실질적으로 순회를 돌려주는 역할을 한다.
    이를 바탕으로 구현된 Class는, 해당 Class 내부에 들어있는 Collection의 순회를 도는 것을 지원할 수 있도록 해준다.
public interface IEnumerator {
	object Current {get;} // 현재 위치 데이터 (현재 위치의 Collection 요소를 return 한다.)
	bool MoveNext(); // 다음 위치로 이동한다. 데이터가 있으면 true, 없으면 false 를 반환한다.
	void Reset(); // index를 초기 위치로 설정한다.
}

IEnumerable (I Enum er able)

Class 내부 Collection 을 반복할 수 있도록 지원하는 IEnumerator를 노출시킨다.

public interface IEnumerable {
	IEnumrator GerEnumerator(); // 말 그대로, IEnumerator를 노출한다. 반환하여, 해당 interface의 정보가 드러나도록 만들어주는 함수를, 해당 class 내에 구현하도록 한다.
}

정리 및 활용

정리

, IEnumerator로 구현된 Class 가 해당 Class 내부에 들어있는 Collection의 직접적인 순회를 책임지며.
IEnumerable 의 경우, IEnumerator 에 관한 정보를 가지고 있다.

예를 들어 설명해본다.

A Class 가 있다고 하자.
List <'A'> 를 Field 로서 가지며, IEnumerator 로 구현된, AEnum Class 가 있다 하자.
AEnum Class는 Field 를 반복하거나 탐색할 수 있다.

이 AEnum 을 Field 로서 가지고 있는, IEnumerable 로 구현된, AEnumerable Class가 있다 하자. 해당 Class 는 GetEnumerator() 가 구현되어 있을 것이고, 해당 GetEnumerator() 는 AEnum을 반환할 것이다.

대강 이렇게 구성되는 것.

활용

IEnumerable 로 구현된, Class 내부에 직접적으로 Collection이 존재하며, GetEnumerator 에서 반환해 줄 때, IEnumerator 를 구현한 Type 을 바로 new 로 생성하여 반환하는 것도 가능하다.

링크의 Person, PeopleEnum, People Class 예시 참고

또한 IEnumerable 이 여러 IEnumerator를 가지고 있을 수도 있다.

foreach

Foreach 의 실체 : GetEnumerator() 함수를 통해 열거자 IEnumerator 객체를 리턴 받고 이를 통해 데이터를 순회한다.
즉, 위의 정리에서의 예시를 바탕으로 생각해보면, foreach(A "변수이름" in "AEnumerable type 에 해당하는 변수이름") 이어야 한다는 것이다.
(위의 A Class, AEnum Class, AEnumerable Class 로서 서술한 예시 참고.)

더 간략하게 정리해보면, 아래 코드와 foreach 가 동일하다고 보면 된다.

IEnumerator e = AEnumerable변수이름.GetEnumerator();
while(e.MoveNext()) {
	// Body for foreach : foreach 안에 들어갈 내용과 동일.
}

yield

Microsoft 에서는 yield keyword 를 실행문에서 사용한다는 것은, yield 가 사용된 그 해당 method, operator, get Accessor 등이 '반복자(Iterator)' 임을 의미한다.

해당 keyword 를 method 에서 사용한 경우를 생각해보자.
즉, yield return 을 사용한 method 는, 위에 따라 반복자가 된다.

  • 반복자가 된 method 를 실행하면, 함수가 실행되는 것이 아닌 yield return 에 따라 구성된 IEnumerator 가 반환된다.
  • 이 IEnumerator 는 method의 구조에 따라 요소가 나누어져 있다. (yield return 이 존재하는 구간마다, 각 method 의 body 가 나뉘어져 있다.) 이 함수들의 부분들을 IEnumerator 에서 사용되는 Collection의 요소처럼 다룬다.
  • 또한, 반복자가 되어 Method 자체에서 IEnumerator 를 반환한다는 점에서, IEnumerable 과 동일한 역할을 하는 것이기도 하다. (해당 method 는 IEnumerator 를 반환하므로. - IEnumerable 의 역할인 "IEnumerator 를 노출시킨다" 는 것을 수행하고 있음.)

Coroutine

IEnumerator 와 yield 를 이용하여, 일반적인 상황에서 함수의 실행이 직렬적으로 처리되던 것을 별도의 Thread 처럼 실행시킬 수 있도록 만든 것.

아래 내용은 알고 있는 내용이라 별도 정리 필요성을 못 느껴 수기만 옮긴다.

별도 설명

Coroutine 으로서 IEnumerator 의 반환형태를 가진 method 를 실행한다.
이는 즉, Coroutine 을 통해 IEnumerator method 가 실행된 경우, foreach 의 형태처럼 해당 함수의 부분들이 실행되나, 반환 받는 것에 따라 Unity 내부적, 혹은 C# 내부적으로 마련되어져 있는 특별한 기능들이 동작한다는 것을 의미한다.

ex - yield return new WaitForSecond(?f); 등.

출처 중 좋아 보이는 곳

profile
오와우아오왕

0개의 댓글