IEnumerator(열거자) : 열거자를 구현하는데 필요한 인터페이스
- 데이터를 리턴(
Getter
)하는 열거자 - 클래스 내부의 컬렉션에 대해 반복할 수 있도록 도와준다.
1 2 3 4 5 6
public interface IEnumerator { object Current { get; } bool MoveNext(); void Reset(); }
- 반복자 구현에 필요한 함수 3 가지를 구현하게 강제하는 인터페이스다.
- 인터페이스는 텅텅 비어있고 아무것도 기능하는게 없다.
- 그 자체로는 반복자를 구현하기 위해선 최소한 저 위의 3 개 함수를 알아서 구현하면 된다. 라고 틀을 잡아주는 것 뿐이다.
IEnumerable : 열거자 IEnumerator를 리턴
- 열거자를 리턴하는
Getter
의Getter
- 열거자
IEnumerator
를Get
하는데 필요한 인터페이스 - 클래스 내부의 컬렉션에 대해 반복할 수 있도록 도와주는 IEnumerator를 노출시킨다.
- 열거할 수 있는 제네릭이 아닌 모든 컬렉션에 대 한 기본 인터페이스.
1 2 3 4
public interface IEnumerable { IEnumerator GetEnumerator(); }
- 객체로
foreach
문을 돌리기 위해서는 그 객체 타입이IEnumerable
을 상속받은 클래스여야 한다. IEnumerable
을 상속받아GetEnumerator
()을 구현한 클래스이어야foreach
로 내부 데이터를 열거할 수 있다.- 이렇게
IEnumerable
로 각각의 독립적인IEnumerator
객체들을 관리할 수도 있다
예제
IEnumerable
상속 및 구현 ```c#
// Simple business object. public class Person { public Person(string fName, string lName) { this.firstName = fName; this.lastName = lName; }
1
2
public string firstName;
public string lastName; } ```
IEnumerator
상속 및 구현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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
// When you implement IEnumerable, you must also implement IEnumerator. public class PeopleEnum : IEnumerator { public Person[] _people; // Enumerators are positioned before the first element // until the first MoveNext() call. int position = -1; // 👉 _people 배열 인덱스로 활용할 것. public PeopleEnum(Person[] list) { _people = list; } public bool MoveNext() { position++; return (position < _people.Length); } public void Reset() { position = -1; } object IEnumerator.Current { get { return Current; } } public Person Current { get { try { return _people[position]; } catch (IndexOutOfRangeException) { throw new InvalidOperationException(); } } } }
IEnumerator
상속받고MoveNext
구현- _
people
의 인덱스position
를 증가시킨다. position
가 _people
배열 크기를 넘어버리는데 도달했다면 더 이상MoveNext
가 불가능하므로false
리턴
- _
Reset
구현- _
people
의 인덱스position
를 -1 로 초기화
- _
Current
구현- 2 가지
Current
를 구현했다.public Person Current
Person
객체인 _people
[position
]를 리턴함.- 이건
IEnumerable
인터페이스를 구현한 프로퍼티가 아니다.Person
리턴이니까..!!
- object
IEnumerator.Current
- 위의
Current
을 실행시켜서 리턴받은Person
객체를object
(System.Object
)로 업캐스팅 형변환해 리턴함
- 위의
- 2 가지
yield
IEnumerable
,IEnumerator
를 상속받는 객체를 간단하게 구현할 수 있는 것이나 마찬가지다. 마치 일시정지와 같은 기능이다.IEnumerable
클래스에서GetEnumerator
() 메서드를 구현하는 한 방법으로 yield 를 사용할 수 있다.- 즉,
GetEnumerator
() 메서드에서yield return
를 사용하여 컬렉션 데이타를 순차적으로 하나씩 넘겨주는 코드를 구현하고, 리턴타입으로IEnumerator
인터페이스를 리턴할 수 있다. C#
에서Iterator
방식으로yield
를 사용하면, 명시적으로 별도의Enumerator
클래스를 작성할 필요가 없다. 컴파일러가 알아서 만들어주기 때문이다!
- 즉,
Result
- C#의 모든
Collections
컬렉션은IEnumerable
,IEnumerator
를 상속받아 구현하고 있다. - 그래서
List
,Array
같은 컬렉션 클래스 객체들을foreach
문에서 돌릴 수 있는 것