yield 키워드는 IEnumerable과 IEnumerator를 쉽게 구현할 수 있도록 도와주는 기능이다.
보통 foreach 문에서 요소를 하나씩 반환하는데 사용되며, 명시적으로 상태를 관리하지 않아도 자동으로 상태를 기억하면서 다음 요소를 반환할 수 있다.
예제: yield return 사용
using System;
using System.Collections.Generic;
public class NumberGenerator
{
// IEnumerable<int>를 반환하는 메서드
public static IEnumerable<int> GetNumbers()
{
yield return 1; // 첫 번째 값 반환
yield return 2; // 두 번째 값 반환
yield return 3; // 세 번째 값 반환
}
}
class Program
{
static void Main()
{
// GetNumbers() 호출 -> IEnumerable<int>을 반환함
foreach (var num in NumberGenerator.GetNumbers())
{
Console.WriteLine(num); // 1, 2, 3 출력
}
}
}
// 1
// 2
// 3
MoveNext()를 수동으로 구현할 필요가 없다!IEnumerator를 직접 구현한 경우
using System;
using System.Collections;
using System.Collections.Generic;
public class CustomEnumerator : IEnumerator<int>
{
private int[] _numbers = { 1, 2, 3 };
private int _position = -1;
public int Current => _numbers[_position];
object IEnumerator.Current => Current;
public bool MoveNext()
{
_position++;
return _position < _numbers.Length;
}
public void Reset() => _position = -1;
public void Dispose() { }
}
IEnumerator를 구현하려면 MoveNext(), Current, Reset() 등을 수동으로 관리해야 해서 코드가 복잡하다.yield return을 사용한 경우
public static IEnumerable<int> GetNumbers()
{
yield return 1;
yield return 2;
yield return 3;
}
IEnumerator를 직접 구현할 필요 없이, 간단하게 순차적인 값 반환을 구현할 수 있다.yield break는 반복을 중단하고 즉시 종료하는 역할을 한다.yield break 사용 예제
using System;
using System.Collections.Generic;
public class NumberGenerator
{
public static IEnumerable<int> GetNumbers()
{
yield return 1;
yield return 2;
yield break; // 여기서 즉시 종료됨 (이후 코드 실행 안 됨)
yield return 3; // 실행되지 않음
}
}
class Program
{
static void Main()
{
foreach (var num in NumberGenerator.GetNumbers())
{
Console.WriteLine(num); // 1, 2만 출력됨
}
}
}
yield break를 만나면 더 이상 요소를 반환하지 않고 즉시 종료된다.using System;
using System.Collections.Generic;
public class EvenNumberGenerator
{
public static IEnumerable<int> GetEvenNumbers(int start, int count)
{
for (int i = 0; i < count; i++)
{
yield return start + (i * 2);
}
}
}
class Program
{
static void Main()
{
foreach (var num in EvenNumberGenerator.GetEvenNumbers(2, 5))
{
Console.WriteLine(num); // 2, 4, 6, 8, 10 출력
}
}
}
yield return을 사용하면 불필요한 리스트 생성 없이 순차적으로 값이 반환된다.using System;
using System.Collections.Generic;
public class InfiniteGenerator
{
public static IEnumerable<int> GenerateInfiniteNumbers()
{
int number = 0;
while (true)
{
yield return number++;
}
}
}
class Program
{
static void Main()
{
foreach (var num in InfiniteGenerator.GenerateInfiniteNumbers())
{
Console.WriteLine(num);
if (num >= 5) break; // 0, 1, 2, 3, 4, 5 출력 후 중단
}
}
}
yield return을 사용하면 불필요한 메모리 할당 없이 필요할 때만 값을 생성할 수 있다.| 기능 | yield return | return |
|---|---|---|
| 반환값 | 여러 개 반환 가능 (순차적) | 한 번만 반환 후 종료 |
| 상태 유지 | 이전 상태를 자동으로 기억 | 상태 유지 X |
| 사용 시점 | IEnumerable<T> 또는 IEnumerator<T> 사용 시 | 일반적인 메서드에서 사용 |
// 비교 예제
public static IEnumerable<int> UseYield()
{
yield return 1;
yield return 2;
yield return 3;
}
public static List<int> UseReturn()
{
return new List<int> { 1, 2, 3 }; // 모든 값을 한 번에 반환
}
// yield return은 하나씩 반환, return은 한 번에 모든 값 반환.
| 개념 | 설명 |
|---|---|
yield return | IEnumerable<T>을 쉽게 구현하여 하나씩 반환 |
yield break | 반복을 즉시 중단 |
| 자동 상태 관리 | 이전 상태를 자동으로 저장 (수동으로 IEnumerator를 구현할 필요 없음) |
| 메모리 최적화 | 모든 데이터를 미리 저장하지 않고, 필요할 때만 생성하여 반환 |
| 반복자(iterator) 구현에 유용 | 무한 반복, 데이터 스트리밍 등에서 사용하기 좋음 |
yield return을 사용하면 IEnumerable을 쉽게 구현 할 수 있다.