메서드를 작성하다 보면 단일의 객체를 반환하기보다 일련의 시퀀스를 반환해야 하는 경우가 종종
있다. 시퀀스를 반환하는 메서드를 작성해야 한다면 컬렉션을 반환하기보다는 이터레이터를 반환하
는 것이 좋다. 이터레이터를 반환하면 이를 이용하여 다양한 작업을 좀 더 수월하게 수행할 수 있기
때문이다.
이터레이터 메서드란 호출자가 요청한 시퀀스를 생성하기 위해서 yield return 문을 사용하는 메서드
를 말한다. 다음에 알파벳 소문자에 대한 시퀀스를 생성하는 매우 기본적인 이터레이터 메서드의
구현 예를 나타냈다.
public static IEnumerable<char> GenerateAlphabet()
{
var letter = 'a';
while (letter <= 'z')
{
yield return letter;
letter++;
}
}
이터레이터 메서드에서 가장 흥미로운 부분은 실상 우리가 작성한 구문이 아니라 컴파일러가 이를
어떻게 해석하고 코드를 생성하는지에 대한 부분이다. 앞에서와 같이 코드를 작성하면 다음과 유사
한 클래스가 생성된다.
class EmbeddedIterator : IEnumerable<char>
{
public IEnumerator<char> GetEnumerator() =>
new LetterEnumerator();
IEnumerator IEnumerable.GetEnumerator() =>
new LetterEnumerator();
public static IEnumerable<char> GenerateAlphabet() =>
new EmbededIterator();
private class LetterEnumerator : IEnumerator<char>
{
private char letter = (char)('a' - 1);
public bool MoveNext()
{
letter++;
return letter <= 'z';
}
public char Current => letter;
object IEnumerator.Current => letter;
public void Reset() =>
letter = (char)('a' - 1);
void IDisposable.Dispose() { }
}
}
이터레이터 메서드가 호출되면 앞에서와 같이 컴파일러가 생성한 객체가 인스턴스화된다. 이후
시퀀스 내에 포함된 항목을 요청하면 비로소 시퀀스가 생성된다. 이러한 동작 방식은 시퀀스의
크기가 작은 경우에는 별다를 바가 없다. 하지만 다음의 예와 같이 .NET Framework의
Enumerable.Range()를 사용하여 int 타입으로 표현 가능한 음이 아닌 정수의 시퀀스를 모두 요청하는