Range Over Iterators in Visual Basic .NET

Visual Basic .NET doesn’t have built-in support for iterators in the same way as the provided example. However, we can implement similar functionality using IEnumerable and yield statements. Here’s an equivalent implementation:

Imports System
Imports System.Collections.Generic

' Let's look at the List(Of T) type
Public Class List(Of T)
    Private Class Element
        Public [Next] As Element
        Public Value As T
    End Class

    Private head As Element
    Private tail As Element

    Public Sub Push(v As T)
        If tail Is Nothing Then
            head = New Element With {.Value = v}
            tail = head
        Else
            tail.Next = New Element With {.Value = v}
            tail = tail.Next
        End If
    End Sub

    ' All returns an IEnumerable(Of T), which is similar to an iterator
    Public Function All() As IEnumerable(Of T)
        Return New AllEnumerable(Me)
    End Function

    Private Class AllEnumerable
        Implements IEnumerable(Of T)

        Private ReadOnly list As List(Of T)

        Public Sub New(list As List(Of T))
            Me.list = list
        End Sub

        Public Function GetEnumerator() As IEnumerator(Of T) Implements IEnumerable(Of T).GetEnumerator
            Return New AllEnumerator(list)
        End Function

        Private Function IEnumerable_GetEnumerator() As System.Collections.IEnumerator Implements IEnumerable.GetEnumerator
            Return GetEnumerator()
        End Function
    End Class

    Private Class AllEnumerator
        Implements IEnumerator(Of T)

        Private ReadOnly list As List(Of T)
        Private current As Element

        Public Sub New(list As List(Of T))
            Me.list = list
            Me.current = Nothing
        End Sub

        Public ReadOnly Property Current As T Implements IEnumerator(Of T).Current
            Get
                If current Is Nothing Then
                    Throw New InvalidOperationException()
                End If
                Return current.Value
            End Get
        End Property

        Private ReadOnly Property IEnumerator_Current As Object Implements IEnumerator.Current
            Get
                Return Current
            End Get
        End Property

        Public Function MoveNext() As Boolean Implements IEnumerator.MoveNext
            If current Is Nothing Then
                current = list.head
            Else
                current = current.Next
            End If
            Return current IsNot Nothing
        End Function

        Public Sub Reset() Implements IEnumerator.Reset
            current = Nothing
        End Sub

        Private disposedValue As Boolean

        Protected Overridable Sub Dispose(disposing As Boolean)
            If Not disposedValue Then
                If disposing Then
                    ' TODO: dispose managed state (managed objects)
                End If
                disposedValue = True
            End If
        End Sub

        Public Sub Dispose() Implements IDisposable.Dispose
            Dispose(disposing:=True)
            GC.SuppressFinalize(Me)
        End Sub
    End Class
End Class

' Fibonacci sequence generator
Public Iterator Function GenFib() As IEnumerable(Of Integer)
    Dim a As Integer = 1
    Dim b As Integer = 1
    While True
        Yield a
        Dim temp As Integer = a
        a = b
        b = temp + b
    End While
End Function

Module Program
    Sub Main()
        Dim lst As New List(Of Integer)()
        lst.Push(10)
        lst.Push(13)
        lst.Push(23)

        ' We can use the All() method in a For Each loop
        For Each e In lst.All()
            Console.WriteLine(e)
        Next

        ' Collect all elements into a list
        Dim all As List(Of Integer) = lst.All().ToList()
        Console.WriteLine("all: " & String.Join(", ", all))

        ' Use the Fibonacci generator
        For Each n In GenFib().Take(6)
            Console.WriteLine(n)
        Next
    End Sub
End Module

This example demonstrates how to implement a custom collection with an iterator-like behavior in Visual Basic .NET. The List(Of T) class provides an All() method that returns an IEnumerable(Of T), which can be used in For Each loops.

The GenFib() function is an example of an infinite sequence generator using the Iterator keyword and Yield statement in Visual Basic .NET.

To run this program, save it as a .vb file and compile it using the Visual Basic compiler. Then run the resulting executable.

$ vbc Program.vb
$ Program.exe
10
13
23
all: 10, 13, 23
1
1
2
3
5
8

This example showcases how to create custom enumerables and use them in Visual Basic .NET, which provides similar functionality to the iterators in the original example.