본문 바로가기
개발일지/C#

yield

by 태운콩즙 2024. 10. 1.
728x90
반응형

yield

yield 키워드는 호출자에게 컬렉션 데이터를 하나씩 리턴 할 때 사용한다

흔히 Enumerator(반복자 , Iterator)라고 불리 우는 이런 기능은 집합 적 인 데이터 셋으로 부터 데이터를 하나씩 호출자에게 보내주는 역할을 한다

yield는 yield return 또는 yield break 의 2가지 방식으로 사용되는데

(1) yield return은 컬렉션 데이터 를 하나씩 리턴 하는데 사용되고

(2) yield break는 리턴을 중지하고 Iteration 루프 를 빠져 나올 때 사용한다

예제)

using System;
using System.Collection.Generic;

class Test
{
	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개의 return문을 가지고 있다

만약 외부에서 이 GetNumber()를 호출하게 되면 첫 번째 호출 시에 yield return 10 을 실행하게 되고

두 번째로 호출하게 되면 20을 리턴 하게 된다

이러한 방식으로 GetNumber()은 모든 값을 한번에 리턴 하는 것이 아니라 호출 시 마다 yield return 문의 값을 리턴 하는 것이다

yield가 유용하게 사용되는 경우

  • 데이터의 양이 커서 모든 데이터를 한번에 리턴 하는 것 보다 조금씩 리턴 하는 것이 더 효율 적일 경우
    • 어떤 자료를 검색 했을 때 1만 개의 자료를 UI에서 10개씩 만 On Demand로 표시해 주는 게 좋을 수도 있다 사용자가 얼마나 원하는 지 모르기 때문에 일종의 지연 실행을 수행 하는 것이 나을 수 있다
  • 어떤 메서드 가 무제한의 데이터를 리턴 하는 경우
    • 랜덤 숫자를 계속 리턴 하는 함수는 결국 전체 리스트를 리턴 할 수 없기 때문에 yield를 사용해서 구현하게 된다
  • 모든 데이터를 미리 계산하면 속도가 느려서 그때 그때 On Demand 로 처리하는 것이 좋은 경우
    • 소수를 계속 리턴 하는 함수의 경우 수소 전체를 구하면 시간 상 많은 계산 시간이 필요함으로 다음 소수 만 리턴 하는 함수를 만들어 소요 시간을 분산 하는 지연 계산을 구현 할 수 있다

yield와Enumetator

c#에서 yield가 자주 사용 되는 곳은 집합 적 데이터를 가지고 있는 컬렉션 클래스 이다

일반적으로 컬렉션 클래스 는 데이터 요소를 하나하나 사용하기 위해 흔히 Enumetator(반복자, Iterator)를 구현하는 경우가 많은데 Enumetator 를 구현하는 방법으로는 yield를 사용 할 수 있다

컬렉션 타입 혹은 Enumerable 클래스에서 GetEnumetator() 메서드를 구현하는 한 방법으로 yield 를 사용 할 수 있다

GetEnumetator() 메서드에서 yield return을 사용하여 컬렉션 데이터를 순차적으로 하나씩 넘겨주는 코드를 구현하고 리턴 타입으로 IEnumerator 클래스를 작성할 필요가 없다

예제)

using System;
using System.Collections;

namespace ConsoleApp1
{
    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);
            it.MoveNext();
            Console.WriteLine(it.Current);
        }
    }
}

위의 예제는 MyList 라는 컬렉션 타입에 있는 데이터를 하나 씩 리턴 하는 GetEnumerator() 메서드의 샘플 코드이다

예제의 GetEnumerator() 메서드는 데이터를 하나씩 리턴하기 위해 yield return문을 while 루프 안에서 사용하고 있다

클래스 안의 샘플 data는 1부터 5까지 정수인데 외부 호출자가 순차적으로 호출하면 yield return에서 하나씩 리턴한다

호출자가 이 메서드를 사용하는 방법은

  • foreach문을 사용하여 C#에서 자동으로 Iterator 루프 처리를 하게 하는방법
  • GetEnumerator() 으로 부터 IEnumerator 인터페이스를 얻어 MoveNext() 메서드와 Current 속성을 사용 하여 개발자가 직접 수동으로 요소를 하나씩 사용하는 방법

일반적으로 그 편리성 때문에 foreach문을 사용하는 방식을 사용한다

728x90
반응형

'개발일지 > C#' 카테고리의 다른 글

회계 관리 프로그램 예제  (1) 2024.11.09
인사 급여 관리 프로그램 예제  (0) 2024.11.08
C# Delegate  (2) 2024.10.02
C# Indexer  (0) 2024.10.02
C#) ref  (0) 2024.10.01