프로그래밍도서관 개발자 .NET / 중급 VB.NET 개발자

Visual Basic에서 이터레이터(Enumerable / Iterator 용어)의 구현 및 적용 방법과 사용자 정의 반복 가능 컬렉션을 만드는 방법에 대해 설명하십시오.

Hintsage AI 어시스턴트로 면접 통과

답변.

질문 역사
이터레이터는 반복해야 할 컬렉션의 출현과 함께 프로그래밍 언어의 중요한 부분이 되었습니다. Visual Basic은 .NET 버전부터 IEnumerable/IEnumerator 지원을 추가하여 자신만의 반복 가능한 컬렉션을 구현하고 For Each 루프를 통해 컬렉션의 내용을 간편하고 간결하게 접근할 수 있게 되었습니다.

문제
많은 개발자들은 내장 컬렉션만 사용하거나 IEnumerable 인터페이스를 제대로 구현하지 않아 For Each를 통한 객체의 반복이 불가능합니다. 또한, Current 및 MoveNext를 통한 이터레이터 상태 구현과 유지 관리가 어렵습니다.

해결책
반복을 지원하기 위해 유형은 IEnumerable(또는 일반 IEnumerable(Of T)) 인터페이스를 구현합니다. IEnumerator를 구현하는 객체를 반환하는 GetEnumerator 함수를 구현합니다. VB.NET에서는 Yield 키워드를 사용하여 이터레이터 메서드도 사용할 수 있으며(VB 2015부터) 반복 구현이 크게 간소화됩니다.

코드 예제:

Imports System.Collections Public Class SimpleCollection Implements IEnumerable Private arr() As Integer = {1, 2, 3} Public Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator For Each i In arr Yield i ' VB 2015+ 사용 Next End Function End Class ' 사용 예: For Each n As Integer In New SimpleCollection() Console.WriteLine(n) Next

주요 특징:

  • For Each를 지원하려면 유형이 IEnumerable / IEnumerable(Of T)를 구현해야 합니다.
  • 구현은 보통 기존 컬렉션에 위임되거나 사용자 정의로 생성됩니다.
  • Yield를 사용하면 이터레이터를 쉽게 만들 수 있으며, Yield 없이 구현하는 경우 IEnumerator를 수동으로 구현해야 합니다.

트릭 질문.

For Each를 지원하기 위해 IEnumerable와 IEnumerator 두 인터페이스를 모두 구현해야 하나요?

아니요, IEnumerable를 구현하고 호환 가능한 이터레이터를 반환하면 충분합니다. 반복 구현을 원하시면 내장 컬렉션의 기존 IEnumerator를 사용할 수 있습니다. 그러나 완전한 사용자 정의를 위해서는 두 부분 모두 구현이 필요합니다.

코드 예제:

Public Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator Return arr.GetEnumerator() ' 내장 배열 이터레이터 사용 End Function

Visual Basic에서 IEnumerable를 명시적으로(Explicit Interface Implementation)만 구현할 수 있나요?

네, 명시적으로 인터페이스를 구현할 수 있습니다. 특히 컬렉션이 이미 자신의 GetEnumerator를 가지고 있고 인터페이스 구현을 숨기고 싶을 때 유용합니다. 이렇게 구현한 GetEnumerator를 직접 호출할 수는 없지만 For Each는 작동합니다.

코드 예제:

Public Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator ' ...메소드 본문 End Function

GetEnumerator가 Nothing을 반환하면 어떻게 되나요?

컬렉션 반복을 처음 시도할 때 예외가 발생합니다. For Each는 유효한 이터레이터를 기대하기 때문입니다.

일반적인 실수 및 안티패턴

  • MoveNext/Current 메서드의 잘못된 구현으로 인해 요소가 건너뛰어지거나 오류가 발생합니다.
  • 호출 간 이터레이터 상태가 손상됨(예: 반복할 때 인덱스가 재설정되지 않음).
  • 누락되거나 부적절한 StopIteration 예외.

실제 사례

부정적인 사례

컬렉션 클래스가 IEnumerable을 구현하지 않았고 별도의 Next 메서드가 요소 반복을 위해 생성되었습니다. 결국 이러한 경우 일반적인 방법이나 For Each에서 사용할 수 없으므로 추가 메서드를 작성해야 합니다.

장점:

  • 문제 해결에 대한 빠른 구현.

단점:

  • For Each 및 LINQ를 사용할 수 없습니다.
  • .NET API와의 호환성을 잃습니다.

긍정적인 사례

개발자가 IEnumerable 및 GetEnumerator를 구현함으로써 컬렉션이 이제 For Each와 함께 작동하고 LINQ와 통합됩니다.

장점:

  • .NET 인프라와의 뛰어난 호환성.
  • 범용성과 사용의 용이함.

단점:

  • Yield가 도입되기 전 수동 구현 시 약간의 코드가 더 필요합니다.