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 CurrentPerson객체인 _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문에서 돌릴 수 있는 것