[Effective C#] 아이템 29: 컬렉션을 반환하기보다 이터레이터를 반환하는 것이 낫다
C# 카테고리의 다른 글
LINQ 개요
- LINQ는 C# 3.0에 추가된 기능이다.
- LINQ는 지연된 쿼리를 지원한다.
- 다양한 저장소에 대해 쿼리를 수행할 수 있다.
- 쿼리 제공자를 자유롭게 구현할 수 있다.
이터레이터 메서드는 호출자가 요청한 시퀀스를 생성하기 위해서 yield return 문을 사용하는 메서드를 말한다.
public static IEnumerable<char> GenerateAlphabet()
{
var letter = 'a';
while (letter <= 'z')
{
yield return letter;
letter++;
}
]
이터레이터는 데이터를 필요할 때 생성한다.
다음은 first와 last를 매개변수를 입력 받아 이터레이터를 반환한다.
public static IEnumerable<char> GenerateAlphaSubset(char first, char last)
{
if (first < 'a' || first > 'z')
throw new ArgumentException("a <= first <= z 이어야 합니다.", nameof(first));
if (last < first || last > 'z')
throw new ArguemntException("first <= last <= z 이어야 합니다.", nameof(last));
var letter = first;
while (letter <= last)
{
yield return letter;
letter++;
}
}
위 코드의 문제점은 시퀀스의 첫 번째 요소가 요청될 때까지 매개변수 값이 유효한지를 확인하는 코드가 수행되지 않는다는 것이다.
이 경우에는 잘못된 인자를 넘겼을 때, 문제를 확인하고 해결하기 까다롭다.
이럴 때는 다음과 같이 수정해야 한다.
public static IEnumerable<char> GenerateAlphaSubset(char first, char last)
{
if (first < 'a' || first > 'z')
throw new ArgumentException("a <= first <= z 이어야 합니다.", nameof(first));
if (last < first || last > 'z')
throw new ArguemntException("first <= last <= z 이어야 합니다.", nameof(last));
return GenerateAlphabetSubsetImpl(first, last);
}
private static IEnumerable<char> GenerateAlphaSubsetImpl(char first, char last)
{
var letter = first;
while (letter <= last)
{
yield return letter;
letter++;
}
}
위와 같이 생성자와 시퀀스 생성 부분을 분리하면 이터레이터가 생성되는 시점에서 인자의 유효성을 검사하게 된다.
이터레이터 메서드를 이용하여 시퀀스를 생성하면 사용자들이 메서드를 폭넓게 사용할 수 있게 된다.
시퀀스를 이용하면 값을 하나씩 가져오기도 용이하고,
ToList() 나 ToArray()와 같은 확장 메서드를 이용하여 컬렉션을 생성하기도 용이하다.
댓글남기기