[C#] 8.2.1 IEnumerable, IEnumerator 인터페이스

ICollection 인터페이스는 C#에서 제공하는 다양한 컬렉션 클랙스들의 기반이 되는 인터페이스입니다. 그리고 ICollection 인터페이스는 IEnumerable 인터페이스를 기반으로 확장된 인터페이스입니다. C#에서 제공되는 컬렉션 개체가 foreach 구문을 통해 보관된 각 요소에 공통적인 작업을 수행할 수 있는 것도 내부적으로 IEnumerable 인터페이스를 기반으로 정의하였기 때문입니다.

IEnuerable 인터페이스에는 foreach 구문에서 필요한 멤버들을 약속한 IEnumerator 개체를 반환하는 GetEnumerator 메서드를 제공하고 있습니다.

▶ IEnumerable, IEnumerator에 약속한 멤버들

간단하게 회원 클래스를 정의하고 회원 개체를 보관하는 컬렉션을 정의해 봅시다.

▶ Member 클래스 정의

▶ Member 개체를 보관하는 MemberCollection 정의

이처럼 MemberCollection을 정의하면 IEnumerator를 참조할 수 있는 GetEnumerator 메서드가 없어서 foreach 구문을 이용하여 보관된 요소에 접근하려고 하면 오류가 발생합니다.

[그림 44] foreach 구문 오류 화면
[그림 44] foreach 구문 오류 화면

이번에는 IEnumerable 인터페이스를 기반으로 MemberCollection 클래스를 정의해 봅시다. 물론, IEnumerable 인터페이스에 약속된 GetEnumerator 메서드를 구체적으로 구현해야 합니다. 여기에서는 MemberCollection 내부에 있는 ArraryList에 보관된 요소에 접근할 수 있는 IEnumerator를 반환할게요. 이처럼 IEnuerator 기반으로 MemberCollection을 정의하면 foreach 구문을 사용할 수 있습니다.

▶ IEnumerable 기반의 MemberCollection 정의

▶ foreach MemberCollection 개체 사용

▶ 실행 결과

그런데 내부에 분리된 여러 멤버를 갖고 있을 때 foreach 문을 이용하여 멤버들을 열거할 수 있게 하려면 어떻게 해야 할까요? 이럴 때에는 IEnuerator 인터페이스를 기반으로 형식을 정의하여 IEnuerator 인터페이스에 약속된 멤버들을 구현합니다.

구체적인 예를 통해 살펴봅시다.

이번에는 수강생과 강사, 강의실을 정의합시다. 강의실에는 강사 한 명과 여러 명의 수강생이 들어갈 수 있고 foreach 문을 이용하여 강의실에 있는 강사와 수강생을 열거할 수 있게 합시다.

먼저, 간단하게 수강생과 강사를 정의합시다.

▶ 수강생과 강사 정의

강의실은 강사 개체를 관리하는 멤버 필드와 수강생들을 보관하는 컬렉션을 멤버로 두겠습니다. 그리고 강사가 들어오는 메서드와 수강생이 들어오는 메서드를 정의합시다.

 

이제 foreach 문을 사용할 수 있게 IEnumerable 인터페이스와 IEnumerator 인터페이스 기반의 형식으로 변경합시다.

물론, IEnumerable 인터페이스와 IEnumerator 인터페이스에 약속한 멤버를 구체적으로 구현해야겠지요. IEnumerable 인터페이스에 약속된 GetEnumerator는 어떻게 구현하면 될까요? 자기 자신이 IEnumerator이므로 자기 자신을 반환하세요.

이제 IEnumerator 인터페이스에 약속한 멤버들을 구현합시다.

foreach 구문을 사용하면 MoveNext 메서드를 호출하여 Current 속성으로 요소를 참조하는 것을 반복합니다. 따라서 내부에는 현재 위치를 기억하기 위한 멤버가 필요합니다.

그리고 foreach 구문을 처음 사용할 때 now값이 초기 상태로 되어야 하므로 강의실 생성자에서 Reset 메서드를 호출할게요.

 

foreach 문은 MoveNext를 먼저 수행한 후에 Current 속성으로 요소를 참조하는 것을 반복하므로 Reset 메서드에서는 now의 초기값을 -1로 설정할게요.

 

MoveNext에서는 now를 1 증가시키는 작업을 하겠죠.

 

그리고 강사가 없으면 현재 위치인 now가 수강생 수보다 작으면 true를 반환하고 그렇지 않으면 Reset을 호출하여 now를 초기 위치로 변경하고 false를 반환하세요.

 

강사가 있으면 now가 수강생 수보다 작거나 같을 때 true를 반환하고 그렇지 않으면 Reset을 호출하여 now를 초기 위치로 변경하고 false를 반환합니다.

Current 속성에서는 현재 위치의 사람을 반환하면 됩니다. 만약, 강사가 없다면 수강생들을 보관한 tutees 컬렉션의 now 인덱스에 있는 수강생을 반환하면 되겠죠. 그리고 강사가 있고 now가 0이면 강사를 반환합니다. 강사가 있고 now가 0이 아니면 tutees 컬렉션의 now-1 인덱스에 있는 수강생을 반환하세요.

이처럼 내부에 분리되어 있는 멤버를 가지고 있는 개체의 요소들을 foreach 문을 이용하여 열거하고자 하면 IEnuerator 인터페이스 기반의 형식으로 정의하세요.

▶ 강의실 정의 (foreach 문으로 내부에 강사와 수강생을 열거할 수 있음)

다음은 foreach 문을 이용하여 강의실에 있는 요소들을 열거하는 예제입니다.

▶ foreach 문을 이용하여 강의실 개체의 요소들을 열거

▶ 실행 결과