There was a period where
yield
was available in
C#
but not in
vb
. If that was the case in 2010 then check whether the
IEnumerable
interface was available in
vb
in 2010?
If the
IEnumerable
interface was available in
vb
in 2010 then you can implement that interface for a class you create in order to create a
Yield
like functionality. See
this article[
^], it's not actually that hard.
If the
IEnumerable
interface wasn't available in
vb
in 2010 then either see OriginalGriff's answer or implement the code below but remove all of the interface implementations. Not implementing the intefaces means that you won't be able to use
For ... Each
but the
While .MoveNext() = True
code should still work - examples are included below.
For example (I haven't tested this code so there will be typos that should be easy to fix).
First you create a new class that can be enumerated (implements
IEnumerable
). The article I linked above describes all of this in detail but in essence the new class implements
IEnumerable
which means it must have the ability to create and return an object that implements
IEnumerator
.
Public Class VBYield
Implements IEnumerable(Of Integer)
Private _enumerableobject As Integer()
Private _thingenumerator As ThingEnumerator
Public Sub New(EnumerableObject As Integer())
Me._enumerableobject = EnumerableObject
End Sub
Public Function GetEnumerator() As IEnumerator(Of Double) Implements IEnumerable(Of Integer).GetEnumerator
Return New ThingEnumerator(Me._enumerableobject)
End Function
Public Function GetEnumerator1() As IEnumerator Implements Collections.IEnumerable.GetEnumerator
Return Me.GetEnumerator()
End Function
Then we create the enumerator that will be used by the enumerable object. You can see that the array of integers is progressively passed from your code to the
IEnumerable
object and then the
IEnumerator
object. You need to decide if it should be shallow (by reference) or deep (by value) copies based on your needs.
Public Class ThingEnumerator
Implements IEnumerator(Of Integer)
Private _enumerableobject As Integer()
Private _index As Integer
Private _curItem As Integer
Private _lastItem As Integer
Public Sub New(enumerableobject As Integer())
Me._enumerableobject = enumerableobject
Me._index = -1
Me._curItem = Nothing
Me._lastItem = enumerableobject.GetUpperBound(0)
End Sub
Then modify your original code to use this new class. Note that there are two ways to do the enumeration
Sub Main()
Dim enumerablething As VBYield = New VBYield(GenerateNumbers(1,5))
For Each number As Interger in VBYield
Console.WriteLine(number.ToString())
Next
Dim enumeratorofthing As IEnumerator = VBYield.GetEnumerator()
While enumeratorofthing.MoveNext() = True
Console.WriteLine(enumeratorofthing.Current.ToString())
End While
End Sub
Function GenerateNumbers(start As Integer, count As Integer) As Integer()
Dim result(count - 1) As Integer
For i As Integer = 0 To count - 1
result(i) = start + i
Next
Return result
End Function
Then you need to implement the
IEnumerator
interface for the
ThingEnumerator
class.
Public ReadOnly Property Current As Double Implements IEnumerator(Of Integer).Current
Get
If IsNothing(Me._curItem) Then
Throw New InvalidOperationException()
End If
Return Me._curItem
End Get
End Property
Public Function MoveNext() As Boolean Implements IEnumerator.MoveNext
If Me._index = Me._lastItem Then
Return False
End If
Me._index += 1
Me._curItem = Me._enumerableobject(Me._index)
Return True
End Function
Public Sub Reset() Implements IEnumerator.Reset
Me._index = -1
Me._curItem = Nothing
End Sub