닷넷에서 제공하는 인터페이스이다.
IEnumerator를 구현한 객체를 열거자(enumerator)라고 한다.
// 닷넷에 정의돼 있는 IEnumerable 인터페이스
public interface IEnumerable
{
IEnumerator GetEnumerator();
}
// 닷넷에 정의돼 있는 IEnumerator 인터페이스
public interface IEnumerator
{
object Current { get; } // 현재 요소를 반환하는 프로퍼티
bool MoveNext(); // 다음 요소를 가리키는 메서드
void Reset(); // 처음 요소를 가리키는 메서드
}
IEnumerable 인터페이스를 구현한 대표적인 예가 System.Array이다.
IEnumerable의 구현체는 다음과 같이 열람하는 것이 가능하다.
int[] intArray = new int[] { 1, 2, 3, 4, 5 };
IEnumerator enumerator = intArray.GetEnumerator();
while (enumerator.MoveNext()) // 더 이상 열거할 수 없을 때 false를 반환
{
Console.Write(enumerator.Current + ", ");
}
// 출력:
// 1, 2, 3, 4, 5,
int[] intArray = new int[] { 1, 2, 3, 4, 5 };
foreach (int elem in intArray)
{
Console.Write(elem + ", ");
}
// 출력:
// 1, 2, 3, 4, 5,
두 코드는 동일한 기능을 한다.
실제로 컴파일러는 컴파일 시점에 아래의 foreach문을 위의 while문으로 변환한다.
즉 IEnumerable, IEnumerator 두 인터페이스를 구현해준다면 개발자가 직접 정의한 구현체도 foreach문으로 열람이 가능하다.
정리하면
IEnumerable: 열거할 수 있는 객체라는 개념
IEnumerator: 실질적으로 열거되는 객체
구현체 예시
class Hardware { }
class USB
{
string name;
public USB(string name) { this.name = name; }
public override string ToString()
{
return name;
}
}
class Notebook : Hardware, IEnumerable
{
USB[] usbList = new USB[] { new USB("USB1"), new USB("USB2") };
public IEnumerator GetEnumerator()
{
return new USBEnumerator(usbList);
}
public class USBEnumerator : IEnumerator
{
int pos = -1;
int length = 0;
object[] list;
public USBEnumerator(USB[] usb)
{
list = usb;
length = usb.Length;
}
public object Current
{
get { return list[pos]; }
}
public bool MoveNext()
{
if (pos >= length - 1)
{
return false;
}
pos++;
return true;
}
public void Reset()
{
pos = -1;
}
}
}
class Program
{
static void Main(string[] args)
{
Notebook notebook = new Notebook();
foreach (USB usb in notebook)
{
Console.WriteLine(usb);
}
}
}
// 출력:
// USB1
// USB2
참고 자료
시작하세요! C# 10 프로그래밍 - 정성태