물에 사는 벌레
C#의 IEnumerator에 대해 알아보자 본문
유니티 스타일의 코루틴 구현하기에 앞서 IEnumerator를 살짝 맛보기로 한다.
이것을 사용하기 전에 먼저 System.Collection 네임스페이스를 사용해야 한다.
using System;
using System.Collections;
예제로 아주 간단한 열거자 사용을 해 보자.
static IEnumerator TestIEnumerator()
{
Console.WriteLine("1");
Console.WriteLine("2");
Console.WriteLine("3");
yield return null;
}
static void Main(string[] args)
{
IEnumerator testIEnumerator = TestIEnumerator();
testIEnumerator.MoveNext();
}
우선 열거자의 마지막 줄을 보면 null을 반환하는 모습을 볼 수 있다.
또한 열거자를 마치 변수처럼 대입하여 사용하는 형태가 보이며,
마지막으로 MoveNext 메서드가 등장하는데 이 메서드를 통하여 열거자를 실행시키고 있다.
* 참고로 MoveNext 메소드를 두 번 이상 실행하면 아무런 변화도 생기지 않습니다. 이유는 다음 코드에서 설명한다.
정리하자면
1. 열거자는 최소 한 개의 yield 문을 가지고 있어야 한다.
2. 열거자는 변수처럼 대입하여 사용할 수 있다.
3. MoveNext 메소드를 통해 열거자 내부의 내용을 실행할 수 있다.
이번에는 조금 다르게 사용해 본다.
class Program
{
static IEnumerator TestIEnumerator()
{
Console.Write("첫 번째 반환: ");
yield return 1;
Console.Write("두 번째 반환: ");
yield return 2;
Console.Write("세 번째 반환: ");
yield return 3;
Console.WriteLine("반환 끝");
}
static void Main(string[] args)
{
IEnumerator testIEnumerator = TestIEnumerator();
Console.WriteLine(testIEnumerator.Current == null ? "null" : "");
testIEnumerator.MoveNext();
Console.WriteLine(testIEnumerator.Current);
testIEnumerator.MoveNext();
Console.WriteLine(testIEnumerator.Current);
testIEnumerator.MoveNext();
Console.WriteLine(testIEnumerator.Current);
testIEnumerator.MoveNext();
// 출력
// null
// 첫 번째 반환: 1
// 두 번째 반환: 2
// 세 번째 반환: 3
// 반환 끝
}
}
열거자 내부 구현이 전부 yield return ...으로 바뀌었다.
그리고 MoveNext 메소드가 여러 번 실행되며, Current 프로퍼티를 통하여 열거자의 현재 값을 출력하려는 시도가 보인다.
코드를 설명하자면 맨 처음 열거자의 Current는 null로 시작하여 MoveNext를 실행할 때 마다 열거자 내부의 반환값인 1, 2, 3이 순차적으로 Current에 대입되는 모습을 볼 수 있다.
이를 잘 알기 위해서는 yield에 대하여 알아야 하는데 그냥 반환이 아닌 yield(양보) 반환은 열거자 내에 존재할 때, MoveNext 메서드를 실행 시 마지막 반환이 있던 코드의 다음 줄 부터 마지막 반환의 다음 반환까지의 코드를 실행하게 된다.
그리고 Current 프로퍼티는 반환된 값을 가리키고 있게 된다.
같은 말이 여러 번 나오니 조금 헷갈리는데, 하니씩 풀어 보면
static IEnumerator TestIEnumerator()
{
Console.Write("첫 번째 반환: "); //1
yield return 1; //2
Console.Write("두 번째 반환: "); //3
yield return 2; //4
Console.Write("세 번째 반환: "); //5
yield return 3; //6
Console.WriteLine("반환 끝"); //7
}
열거자에 대하여 MoveNext를 실행하기 전의 Current는 null이다.
이후 MoveNext를 처음 실행하면 2번째 줄 까지 코드가 실행되고 Current는 1이 된다.
다음 MoveNext 실행 시 3번 줄 부터 4번 줄 까지 실행되고 Current는 2가 된다.
또 다음 실행은 5번 줄 부터 6번 줄까지 실행되고 Current가 3이 되며,
마지막 실행에서는 7번 줄만 실행되어 반환 끝 메시지가 출력되고 Current는 여전히 3으로 유지된다.
고로 실행 순서는 1~2, 3~4, 5~6, 7 이 된다.
이를 활용하여 최종적으로 코드를 간단하게 줄일 수 있다.
class Program
{
static IEnumerator TestIEnumerator()
{
yield return 1;
yield return 2;
yield return 3;
}
static void Main(string[] args)
{
IEnumerator testIEnumerator = TestIEnumerator();
while(testIEnumerator.MoveNext() == true)
{
Console.WriteLine(testIEnumerator.Current);
}
// 출력
// 1
// 2
// 3
}
}
MoveNext 메소드는 현재 yield return 줄을 기준으로 다음 코드가 존재하면 true 아니면 false를 반환한다.
이를 이용하여 코드를 다음 반환까지 실행함과 동시에 다음 코드가 존재하는지 검사도 하고 있다.
'C#' 카테고리의 다른 글
유니티 스타일의 코루틴 구현하기 (0) | 2019.07.14 |
---|