ProgramaciónDesarrollador VB.NET

Describe cómo funciona el ciclo For...Each...Next en Visual Basic con colecciones personalizadas. ¿Cómo crear una colección propia para iterar en For Each y qué se debe implementar para ello?

Supere entrevistas con el asistente de IA Hintsage

Respuesta.

Historia de la pregunta:

El operador For Each...Next en Visual Basic permite iterar sobre los elementos de colecciones o matrices. Desde VB6 se soportó la iteración sobre colecciones estándar, y en VB.NET — sobre todos los tipos que implementan una interfaz específica. Sin embargo, cuando se requieren crear colecciones personalizadas para la iteración, es importante implementar correctamente la infraestructura necesaria.

Problema

No es suficiente con implementar el almacenamiento de elementos: los operadores For Each requieren el soporte de la interfaz especializada IEnumerable. A menudo, las colecciones personalizadas se limitaban a los métodos Add/Get, transformando el objeto en una "caja negra" para iterar. Esto impedía la integración con la estructura de iteración del lenguaje y causaba errores.

Solución

Para que For Each funcione correctamente con tu colección, es necesario implementar la interfaz IEnumerable, y para soportar el trabajo con elementos tipados — IEnumerable(Of T). Debes crear también un enumerador propio (Enumerator) que implemente la interfaz IEnumerator (o IEnumerator(Of T) en versiones genéricas).

Ejemplo:

Public Class IntCollection Implements IEnumerable(Of Integer) Private ReadOnly items As New List(Of Integer)() Public Sub Add(value As Integer) items.Add(value) End Sub Public Function GetEnumerator() As IEnumerator(Of Integer) _ Implements IEnumerable(Of Integer).GetEnumerator Return items.GetEnumerator() End Function Private Function IEnumerable_GetEnumerator() As IEnumerator _ Implements IEnumerable.GetEnumerator Return GetEnumerator() End Function End Class ' Uso: Dim col As New IntCollection() col.Add(10) col.Add(20) col.Add(30) For Each n As Integer In col Console.WriteLine(n) Next

Características clave:

  • Se requiere la implementación de los métodos GetEnumerator y devolver IEnumerator o IEnumerator(Of T).
  • Soporte para IEnumerable genérico y no genérico para compatibilidad con diferentes versiones del entorno.
  • La colección construida puede participar en LINQ, For Each y trabajar con la infraestructura estándar de .NET.

Preguntas trampa.

¿Se puede implementar For Each sin la interfaz IEnumerable, simplemente escribiendo un método GetEnumerator?

No, Visual Basic requiere el soporte oficial de la interfaz IEnumerable/IEnumerable(Of T) para que el compilador reconozca la colección como compatible con For Each.

¿Debe el enumerador ser una clase separada?

No, si la base de datos de elementos soporta un enumerador estándar (por ejemplo, si agregas una List(Of T)), puedes devolver su GetEnumerator. Solo en escenarios complejos puede que se necesite una implementación propia de IEnumerator.

¿Se puede modificar la colección dentro del ciclo For Each?

No, modificar la colección durante la iteración provocará una InvalidOperationException. Se necesitan estrategias especiales para un manejo correcto (por ejemplo, copiar la lista antes de iterar o usar indexación).

Errores comunes y antipatróns

  • Implementar solo Add/Remove sin IEnumerable — no se puede usar For Each.
  • Devolver enumeradores inexistentes o incorrectos — causa fallos durante la iteración.
  • Modificar la colección dentro del cuerpo del ciclo For Each.

Ejemplo de la vida real

Caso negativo

En la empresa se desarrolló una clase MyCollection con adiciones y eliminaciones a través de un array, pero sin implementar la interfaz IEnumerable. For Each no funcionaba, teniendo que usar ciclos normales y un campo público con los elementos.

Pros:

  • Rápida creación de la colección — mínimo código.

Contras:

  • No se podía usar For Each, LINQ, no se podía trabajar con ellos como colecciones estándar.
  • Apareció código duplicado de iteración en diferentes lugares.

Caso positivo

La clase fue reformulada, implementando IEnumerable(Of T). Después de eso, la colección se utilizó fácilmente y de manera estándar en For Each, además se volvió compatible con LINQ.

Pros:

  • Sintaxis limpia y estándar.
  • La iteración de la colección es compatible con todas las capacidades de infraestructura de VB.NET.

Contras:

  • Se requiere agregar más código para soportar las interfaces.