C#에서 yield 키워드 사용법
yield
키워드 작동 방식
yield
키워드는 yield return
또는 yield break
두 가지 형식으로 사용됩니다.
yield return
: 컬렉션의 다음 요소를 반환합니다.yield break
: 이터레이션을 중단하고 메서드 실행을 종료합니다.
예제 코드를 통해 yield
키워드의 작동 방식을 살펴보겠습니다.
using System;
public class MyNumbers
{
public IEnumerable GetNumbers()
{
for (int i = 0; i < 10; i++)
{
yield return i; // 하나씩 요소를 반환
}
}
}
class Program
{
static void Main(string[] args)
{
foreach (int num in new MyNumbers().GetNumbers())
{
Console.WriteLine(num);
}
}
}
위 예제에서 MyNumbers.GetNumbers()
메서드는 yield return
키워드를 사용하여 0부터 9까지의 숫자를 하나씩 순환하여 제공합니다. foreach
루프에서는 이 메서드를 호출하여 반환된 숫자들을 차례대로 출력합니다.
yield
키워드의 장점
yield
키워드를 사용하는 이터레이터 메서드는 다음과 같은 장점을 제공합니다.
- 메모리 효율성: 모든 요소들을 미리 로드하지 않고 필요한 만큼만 순환하기 때문에 대량의 데이터를 처리할 때 특히 유용합니다.
- 코드 간결성: 기존의 반복 루프를 사용하는 것보다 코드를 간결하게 작성할 수 있습니다.
- 지연 평가: 실제 데이터 처리를 필요한 시점까지 미룰 수 있어 유연성을 제공합니다.
yield
키워드 활용 예제
다음은 yield
키워드를 활용하는 다양한 예제입니다.
- 무한 시퀀스 생성: 제한 없이 요소를 생성하는 이터레이터 메서드를 만들 수 있습니다.
- 파일 처리: 큰 파일을 한 번에 로드하지 않고 한 줄씩 처리하는 이터레이터 메서드를 만들 수 있습니다.
- 데이터 압축: 데이터 압축 알고리즘에서 데이터를 차례대로 처리하는 이터레이터 메서드를 사용할 수 있습니다.
결론
예제 코드
무한 시퀀스 생성
using System;
public class InfiniteNumbers
{
public IEnumerable GetInfiniteNumbers()
{
int i = 0;
while (true)
{
yield return i++; // 무한히 0부터 증가하는 숫자를 반환
}
}
}
class Program
{
static void Main(string[] args)
{
foreach (int num in new InfiniteNumbers().GetInfiniteNumbers())
{
if (num > 10) break; // 10까지 출력하고 루프 종료
Console.WriteLine(num);
}
}
}
위 코드는 0
부터 무한히 증가하는 숫자를 반환하는 GetInfiniteNumbers()
이터레이터 메서드를 만듭니다. foreach
루프에서는 이 메서드를 호출하여 숫자를 10개까지 출력합니다.
파일 처리
using System;
using System.IO;
public class FileProcessor
{
public IEnumerable ProcessLines(string filePath)
{
using (StreamReader reader = new StreamReader(filePath))
{
string line;
while ((line = reader.ReadLine()) != null)
{
yield return line; // 파일의 각 행을 반환
}
}
}
}
class Program
{
static void Main(string[] args)
{
foreach (string line in new FileProcessor().ProcessLines("input.txt"))
{
Console.WriteLine(line);
}
}
}
위 코드는 ProcessLines()
이터레이터 메서드를 사용하여 파일의 각 행을 차례대로 처리합니다. 이 메서드는 StreamReader
객체를 사용하여 파일을 한 줄씩 읽고 각 행을 반환합니다.
데이터 압축
using System;
using System.IO;
public class DataCompressor
{
public IEnumerable CompressData(byte[] data)
{
// 실제 압축 알고리즘 구현 (예: Huffman coding)
foreach (byte b in data)
{
// 압축된 데이터를 반환
yield return compressedByte;
}
}
}
class Program
{
static void Main(string[] args)
{
byte[] data = File.ReadAllBytes("data.bin");
foreach (byte b in new DataCompressor().CompressData(data))
{
// 압축된 데이터 처리
}
}
}
위 코드는 CompressData()
이터레이터 메서드를 사용하여 데이터를 압축합니다. 이 메서드는 실제 압축 알고리즘을 구현하여 입력 데이터를 차례대로 처리하고 압축된 데이터를 반환합니다.
C#에서 yield
키워드의 대체 방법
다음은 yield
키워드 대신 사용할 수 있는 몇 가지 방법입니다.
직접 반복 루프 사용:
간단한 시퀀스를 처리하는 경우 foreach
루프와 같은 직접적인 반복 루프를 사용하는 것이 더 간편할 수 있습니다.
int[] numbers = new int[] { 1, 2, 3, 4, 5 };
foreach (int num in numbers)
{
Console.WriteLine(num);
}
IEnumerator 인터페이스 구현:
좀 더 복잡한 시퀀스를 처리하거나 yield
키워드의 모든 기능을 활용하지 못하는 경우 IEnumerator
인터페이스를 직접 구현하는 방법을 사용할 수 있습니다.
public class MyNumbers : IEnumerator
{
private int current = 0;
public bool MoveNext()
{
if (current < 10)
{
Current = current++;
return true;
}
else
{
return false;
}
}
public object Current { get { return current; } }
public void Reset()
{
current = 0;
}
public void Dispose() { }
}
class Program
{
static void Main(string[] args)
{
MyNumbers numbers = new MyNumbers();
foreach (int num in numbers)
{
Console.WriteLine(num);
}
}
}
LINQ 활용:
LINQ(Language Integrated Query)는 데이터 쿼리 및 변환을 위한 강력한 도구입니다. yield
키워드 대신 LINQ를 사용하여 데이터를 처리하는 방법을 고려할 수 있습니다.
int[] numbers = new int[] { 1, 2, 3, 4, 5 };
var evenNumbers = numbers.Where(n => n % 2 == 0);
foreach (int num in evenNumbers)
{
Console.WriteLine(num);
}
기타 라이브러리 활용:
특정한 작업을 수행하는 데 특화된 라이브러리가 존재할 수 있습니다. 예를 들어, 비동기 처리를 위해 async
/await
키워드를 사용하거나, Reactive Extensions를 사용하여 이벤트 기반 데이터 처리를 수행할 수 있습니다.
결론
yield
키워드는 C#에서 이터레이터를 구현하는 유용한 도구이지만, 상황에 따라 더 적합한 대체 방법이 존재할 수 있습니다. 코드 작성 시, 문제 해결에 가장 적합하고 효율적인 방법을 선택하는 것이 중요합니다.
c# yield