Historia del tema
Los iteradores se han convertido en una parte importante de los lenguajes de programación con la aparición de colecciones que deben ser recorridas. En Visual Basic, a partir de la versión .NET, se introdujo el soporte para IEnumerable/IEnumerator, que permite implementar colecciones iterables personalizadas y utilizar el bucle For Each para un acceso conveniente y conciso al contenido de las colecciones.
Problema
Muchos desarrolladores se limitan a usar solo colecciones integradas o no implementan correctamente la interfaz IEnumerable, lo que hace imposible recorrer objetos mediante For Each. Además, la implementación y el mantenimiento del estado del iterador a través de Current y MoveNext puede ser complicado.
Solución
Para soportar iteraciones, el tipo implementa la interfaz IEnumerable (o IEnumerable(Of T) genérica). Implemente la función GetEnumerator, que retorna un objeto que implementa IEnumerator. En VB.NET también se pueden usar métodos de iterador con la palabra clave Yield (desde VB 2015), lo que simplifica mucho la implementación del recorrido.
Ejemplo de código:
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 ' para VB 2015+ Next End Function End Class ' Uso: For Each n As Integer In New SimpleCollection() Console.WriteLine(n) Next
Características clave:
¿Es obligatorio implementar ambas interfaces: IEnumerable e IEnumerator, para soportar For Each?
No, es suficiente implementar IEnumerable y retornar un iterador compatible. Si desea implementar el recorrido, puede utilizar el IEnumerator existente de una colección interna. Pero para una personalización completa, es necesaria la implementación de ambas partes.
Ejemplo de código:
Public Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator Return arr.GetEnumerator() ' usamos el iterador integrado del array End Function
¿Se puede implementar IEnumerable solo explícitamente (Implementación de interfaz explícita) en Visual Basic?
Sí, se puede implementar la interfaz explícitamente, especialmente si su colección ya tiene su propio GetEnumerator y desea ocultar la implementación de la interfaz. No se podrá llamar directamente a ese GetEnumerator, pero For Each funcionará.
Ejemplo de código:
Public Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator ' ...cuerpo del método End Function
¿Qué sucederá si GetEnumerator retorna Nothing?
Se lanzará una excepción en el primer intento de recorrer la colección, ya que For Each espera un iterador válido.
La clase de colección no implementó IEnumerable, y se creó un método separado Next para recorrer elementos. Como resultado, no se puede usar en métodos universales o For Each, y se deben escribir métodos adicionales.
Ventajas:
Desventajas:
El desarrollador implementó IEnumerable y GetEnumerator, ahora la colección funciona con For Each e se integra con LINQ.
Ventajas:
Desventajas: