c# IEnumerable과 IEnumerator

2024. 9. 29. 20:13c#

IEnumerable과 IEnumerator 인터페이스

C#의 IEnumerableIEnumerator는 컬렉션을 반복하는 데 필요한 중요한 인터페이스입니다.
이 글에서는 이 두 인터페이스의 역할과 차이점, 그리고 사용법에 대해 알아보겠습니다.


1. IEnumerable 인터페이스

IEnumerable 인터페이스는 컬렉션이 foreach 루프에서 반복될 수 있도록 해주는 기본적인 인터페이스입니다. IEnumerable을 구현한 클래스는 GetEnumerator() 메서드를 통해 IEnumerator 객체를 반환하여 컬렉션을 순회할 수 있습니다.

IEnumerable의 정의

public interface IEnumerable
{
    IEnumerator GetEnumerator();
}

IEnumerable 인터페이스는 제네릭 버전도 제공되며, 일반적으로 IEnumerable<T>를 더 많이 사용합니다.

public interface IEnumerable<out T> : IEnumerable
{
    IEnumerator<T> GetEnumerator();
}

IEnumerable을 사용하는 이유

IEnumerable을 구현하면, 컬렉션의 내부 구조를 신경 쓰지 않고도 반복할 수 있습니다. 즉, 배열, 리스트, 해시셋과 같은 다양한 컬렉션 타입을 일관된 방법으로 순회할 수 있습니다.

IEnumerable 사용 예제

List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };

foreach (int number in numbers)
{
    Console.WriteLine(number);
}

위의 예제에서 List<T>는 IEnumerable<T>를 구현하고 있으며, foreach 문을 통해 컬렉션의 요소를 반복하고 있습니다.


2. IEnumerator 인터페이스

IEnumerator 인터페이스는 컬렉션의 개별 요소에 대해 순차적으로 접근할 수 있게 해주는 인터페이스입니다. IEnumerator는 현재 요소를 가리키는 커서 개념을 사용합니다.

IEnumerator의 정의

public interface IEnumerator
{
    bool MoveNext();
    object Current { get; }
    void Reset();
}

IEnumerator 인터페이스는 제네릭 버전도 제공됩니다.

public interface IEnumerator<out T> : IDisposable, IEnumerator
{
    new T Current { get; }
}

IEnumerator 메서드 설명

  • MoveNext(): 컬렉션의 다음 요소로 이동하고, 요소가 있으면 true, 없으면 false를 반환합니다.
  • Current: 컬렉션의 현재 요소를 반환합니다.
  • Reset(): 반복을 처음 위치로 다시 설정합니다. (대부분의 컬렉션에서는 잘 사용되지 않습니다.)

IEnumerator 사용 예제

List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
IEnumerator<int> enumerator = numbers.GetEnumerator();

while (enumerator.MoveNext())
{
    int number = enumerator.Current;
    Console.WriteLine(number);
}

이 예제는 IEnumerator를 사용하여 List<int> 컬렉션의 요소들을 반복합니다.
MoveNext()를 호출하여 다음 요소로 이동하고, Current 속성으로 현재 요소를 가져옵니다.


3. IEnumerable과 IEnumerator의 차이점

IEnumerable:

  • IEnumerable은 컬렉션 자체를 나타내는 인터페이스로, 컬렉션을 반복할 수 있도록 해줍니다.
  • GetEnumerator() 메서드를 제공하여 컬렉션의 반복자를 반환합니다.
  • foreach 루프를 지원하며, 주로 외부 반복을 나타냅니다.

IEnumerator:

  • IEnumerator는 컬렉션의 반복자로, 컬렉션의 각 요소에 접근하는 기능을 제공합니다.
  • MoveNext(), Current, Reset() 메서드를 통해 반복을 제어합니다.
  • IEnumerator는 내부 반복을 관리합니다.

4. IEnumerable과 IEnumerator 구현

커스텀 컬렉션을 만들 때 IEnumerableIEnumerator를 직접 구현할 수 있습니다.
아래는 간단한 커스텀 컬렉션의 예제입니다.

IEnumerable과 IEnumerator 구현 예제

public class NumberCollection : IEnumerable<int>
{
    private int[] numbers = { 1, 2, 3, 4, 5 };

    public IEnumerator<int> GetEnumerator()
    {
        return new NumberEnumerator(numbers);
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

public class NumberEnumerator : IEnumerator<int>
{
    private int[] numbers;
    private int position = -1;

    public NumberEnumerator(int[] numbers)
    {
        this.numbers = numbers;
    }

    public int Current
    {
        get
        {
            if (position < 0 || position >= numbers.Length)
                throw new InvalidOperationException();
            return numbers[position];
        }
    }

    object IEnumerator.Current => Current;

    public bool MoveNext()
    {
        position++;
        return (position < numbers.Length);
    }

    public void Reset()
    {
        position = -1;
    }

    public void Dispose() { }
}

이 코드는 IEnumerable<int>과 IEnumerator<int>를 구현하여 커스텀 컬렉션을 정의한 것입니다.
NumberCollection은 숫자를 저장하는 컬렉션이며, NumberEnumerator는 컬렉션을 반복할 수 있도록 합니다.


 

IEnumerableIEnumerator는 C#에서 컬렉션을 순회할 때 필수적인 인터페이스입니다.
IEnumerable은 컬렉션의 외부 반복을 지원하고, IEnumerator는 내부 반복을 관리합니다.
이 두 인터페이스를 적절히 사용하면 복잡한 데이터 구조에서도 간편하게 데이터를 처리할 수 있습니다.