ProgramaciónDesarrollador de bibliotecas .NET / Desarrollador intermedio de VB.NET

Describe las formas de implementar y aplicar iteradores (término Enumerable / Iterator) en Visual Basic, así como cómo crear colecciones iterables personalizadas.

Supere entrevistas con el asistente de IA Hintsage

Respuesta.

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:

  • Para soportar For Each, el tipo debe implementar IEnumerable / IEnumerable(Of T).
  • La implementación generalmente se delega a una colección existente o se crea una propia.
  • Con Yield se pueden crear iteradores fácilmente; sin Yield, se tendrá que implementar IEnumerator manualmente.

Preguntas engañosas.

¿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.

Errores comunes y anti-patrones

  • Implementación incorrecta de los métodos MoveNext/Current, lo que causa que se omitan elementos o produzcan errores.
  • Violación del estado del iterador entre llamadas (por ejemplo, no se restablece el índice al volver a recorrer).
  • Excepción StopIteration ausente o incorrecta.

Ejemplo de la vida real

Caso negativo

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:

  • Implementación rápida según la tarea.

Desventajas:

  • No se puede usar For Each y LINQ.
  • Pérdida de compatibilidad con la API de .NET.

Caso positivo

El desarrollador implementó IEnumerable y GetEnumerator, ahora la colección funciona con For Each e se integra con LINQ.

Ventajas:

  • Súper compatibilidad con la infraestructura de .NET.
  • Versatilidad y facilidad de uso.

Desventajas:

  • Se requiere un poco más de código en la implementación manual antes de la llegada de Yield.