본문 바로가기
C#/이론

[예제로 배우는 C# 프로그래밍]yield

by 단월໒꒱ 2022. 7. 6.

 

C# yield

 

 

yield

 

  yield 키워드는 호출자에게 컬렉션 데이터를 하나씩 리턴할 때 사용한다. 흔히 Enumerator(Iterator)라고 불리는 이 기능은 집합적인 데이터셋으로부터 데이터를 하나씩 호출자에게 보내는 역할으 한다.

 

  yield는 yield return 또는 yield break 2가지 방식으로 사용되는데, 각각의 사용처는 다음과 같다.

    ① yield return : 컬렉션 데이터를 하나씩 리턴하는데 사용

    ② yield break : 리턴을 중지하고 Iteration 루프를 빠져나올 때 사용

 

 

  다음의 예제를 살펴보자.

  

 

using System;
using System.Collections.Generic;

class Program
{
    static IEnumerable<int> GetNumber()
    {
        yield return 10;  // 첫번째 루프에서 리턴되는 값
        yield return 20;  // 두번째 루프에서 리턴되는 값
        yield return 30;  // 세번째 루프에서 리턴되는 값
    }

    static void Main(string[] args)
    {
        foreach (int num in GetNumber())
        {
            Console.WriteLine(num);
        }             
    }
}

 

 

  GetNumber()라는 메서드는 3개의 yield return문을 가지고 있다. 만약 외부에서 이 GetNumber()를 호출하게 되면, 첫번째 호출 시에는 첫번째 yield return 10을 실행하여 10을 리턴하고, 두번째로 호출되면 yield return 20이 실행되어 20을 리턴한다. 이러한 방식으로 GetNumber()는 한번 호출시마다 다음 yield return문의 값을 리턴하는 식으로 동작한다.

 

 

 

yield와 Enumerator

 

  C#에서 yield가 자주 사용되는 곳은 집합 데이터를 가지고 있는 컬렉션 클래스이다. 일반적으로 컬렉션 클래스는 데이터 요소를 하나하나 사용하기 위해 흔히 Enumerator(Iterator)를 구현하는 경우가 많은데, Enumerator를 구현하는 한 방법으로 yield를 사용할 수 있다.

 

  다음 예제는 MyList라는 컬렉션 타입에 있는 데이터를 하나씩 리턴하는 GetEnumerator() 메서드이다. 예제의 GetEnumerator() 메서드는 데이터를 하나씩 리턴하기 위해 yield return문을 while 루프 안에서 사용하고 있다. 클래스 안의 샘플 데이터는 1부터 5까지 숫자인데, 외부 호출자가 순차적으로 호출하면 yield return에서 하나씩 리턴한다.

 

 

using System;
using System.Collections;

public class MyList
{
    private int[] data = { 1, 2, 3, 4, 5 };
    
    public IEnumerator GetEnumerator()
    {
        int i = 0;
        while (i < data.Length)
        {
            yield return data[i];
            i++;                
        }
    }

    //...
}

class Program
{
    static void Main(string[] args)
    {
        // (1) foreach 사용하여 Iteration
        var list = new MyList();

        foreach (var item in list)  
        {
            Console.WriteLine(item);
        }

        // (2) 수동 Iteration
        IEnumerator it = list.GetEnumerator();
        it.MoveNext();
        Console.WriteLine(it.Current);  // 1
        it.MoveNext();
        Console.WriteLine(it.Current);  // 2
    }
}

 

 

 

yield 실행 순서

 

  C#에서 호출자가 yield를 가진 Iteration 메서드를 호출하면 다음과 같은 방식으로 실행된다.

  

  호출자(A)가 IEnumerable을 리턴하는 메서드(B)를 호출하면, yield return문에서 하나의 값을 리턴하고, 해당 메서드(B)의 위치를 기억해둔다. 호출자(A)가 다시 루프를 돌아 다음 값을 메서드(B)에 요청하면, 메서드의 기억된 위치 다음 문장부터 실행하여 다음 yield문을 만나 값을 리턴한다.

 

 

 

댓글