질문 역사
이터레이터는 반복해야 할 컬렉션의 출현과 함께 프로그래밍 언어의 중요한 부분이 되었습니다. 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와 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는 유효한 이터레이터를 기대하기 때문입니다.
컬렉션 클래스가 IEnumerable을 구현하지 않았고 별도의 Next 메서드가 요소 반복을 위해 생성되었습니다. 결국 이러한 경우 일반적인 방법이나 For Each에서 사용할 수 없으므로 추가 메서드를 작성해야 합니다.
장점:
단점:
개발자가 IEnumerable 및 GetEnumerator를 구현함으로써 컬렉션이 이제 For Each와 함께 작동하고 LINQ와 통합됩니다.
장점:
단점: