Notice
Recent Posts
Recent Comments
«   2025/03   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31
Today
Total
Archives
관리 메뉴

cyphen156

C# 반복자 패턴 IEnumerator과 yield키워드 본문

프로그래밍/C#

C# 반복자 패턴 IEnumerator과 yield키워드

cyphen156 2025. 2. 25. 14:58

C#에는 Enumerator라는 반복자가 있다.

의미는 InterFace Enum Iterator를 의미한다.

https://learn.microsoft.com/ko-kr/dotnet/api/system.collections.ienumerator?view=net-8.0

 

IEnumerator 인터페이스 (System.Collections)

제네릭이 아닌 컬렉션에 대한 간단한 반복을 지원합니다.

learn.microsoft.com

왜 쓰는가 하면 foreach라는 구문을 통해 반복 작업을 하고 싶은데 제네릭이 아닌 타입에 대해서도 반복자 지원을 받기 위해 사용하는 인터페이스이다.

public IEnumerator GetEnumerator() 함수를 통해 반복자 객체를 반환할 수 있게 하며 인터페이스를 통해 상속을 구현받고 있기 때문에 이론상 모든 오브젝트를 반복 처리 할 수 있게 해준다.

--> 수정 내부적으로 어딘가에서 들고 있다. 하지만 메모리를 깔 수 없으니 확인이 안된다.

using System;
using System.Collections;

class MyCollection : IEnumerable  // IEnumerable을 구현하면 foreach 사용 가능
{
    private string[] items = { "Apple", "Banana", "Cherry" };

    public IEnumerator GetEnumerator()  // IEnumerator를 반환하는 메서드
    {
        for (int i = 0; i < items.Length; i++)
        {
            yield return items[i];  // `yield return`으로 상태 유지하며 값 반환
        }
    }
}

class Program
{
    static void Main()
    {
        MyCollection collection = new MyCollection();

        foreach (var item in collection)  // `IEnumerator` 덕분에 foreach 사용 가능
        {
            Console.WriteLine(item);
        }
    }
}

유니티 Coroutine에서의 Yield키워드와 진정한 의미

그런데 가만히 보다보면 yield라는 키워드가 하나 존재한다.

이 키워드는 함수의 정적함수화 이자 동적 함수화를 의미하는 것이다. 

무슨 의미냐 하면 원래는 함수가 리턴하면 호출이 종료되어 해당 함수와 관련된 모든 지역변수와 실행 코드들을 메모리 상에서 내려야 한다. 그런데 이것을 정적화(static)처럼 사용하여 중간에 리턴되어도 상태를 저장(정적 저장)할 수 있게 되어 다음에 호출했을 때 저장된 부분부터 다시 이어서 함수를 실행(동적으로 함수를 호출)할 수 있게 되는 것이다.

이것이 왜 필요하는 가 하면 게임이라는 분야에서의 특수성과 비동기 작동이라는 장점 때문이다. 

간단한 예시를 들어보면 

음식점에서 일을 하는데 설거지를 하고 있다. (function 설거지()실행중)

그런데 중간에 손님이 와서 주문을 한다. (function 주문받기()실행해야함)

설거지는 나중에 다시 이어서 해도 되지만 손님의 주문을 받는건 바로 처리하지 않는다면 손님을 놓치게 되는 불상사가 발생한다. 그렇기 때문에 반드시 주문받기()를 실행해야 한다.

그래서 여기까지 설거지를 진행했다는 것을 기록해 놓고, 주문받기를 실행하고 다시 돌아와서 이어서 설거지를 마무리 한다.

한마디로 말해 병렬 처리를 하겠다는 소리다. 

게임에서의 의미는 화면에 렌더링 처리를 하는데 최소한으로 렌더링은 1초에 60번 호출되어 실행되야 한다.

그런데 특정 함수가 연산 완료 까지 예상시간이 5초가 걸린다고 할 때, 저 함수가 완료되기 까지 기다린다면 1프레임 움직임이 5초가 걸리게 되어 1초에 60번 렌더링 되던 것이 5초에 1번 렌더링 되는 불상사가 발생하는 것이다.

이러한 상태를 피하기 위해 ContextSwitching이라는 연산량 증가를 감수하고 서라도 60번의 프레임 보장을 위해 잠시 함수 실행을 저장했다가 돌아와서 이어 하겠다는 소리이다.  

yield라는 키워드는 기본적으로 IEnumerator를 자동 생성하기 때문에 그냥 쓰고 자료형만 리턴해주면 된다.

foreach문에서 yield return Object;를 통해 자동 실행 할 수 있다.

'프로그래밍 > C#' 카테고리의 다른 글

C# 버전별 핵심 기능 (1.0 ~ 7.0)  (0) 2023.12.01
C# 실습 1 .NET 8 Winforms 앱 만들기  (0) 2023.11.30
C#에서 클래스와 namespace(C++와 다른점 2)  (0) 2023.11.29
C# 기초2 C/C++와 다른점  (2) 2023.11.28
C# 기초1  (0) 2023.11.28