I know it's been a while since you asked the question, but I was having the same problem of not having a 'yield' keyword in VB. This is what I found and have been using in its stead. You can implement 'yield' with a GenericIterator, here is code for such an Iterator:
Public Class GenericIterator(Of T)
Implements IEnumerable(Of T)
Implements IEnumerator(Of T)
Public Delegate Function MoveNextFunc(ByRef nextItem As T) As Boolean
Private _Current As T
Private _func As MoveNextFunc
Public Sub New(ByVal func As MoveNextFunc)
_func = func
End Sub
Public Function MoveNext() As Boolean Implements IEnumerator.MoveNext
Return _func(_Current)
End Function
Public Function GetEnumerator() As IEnumerator(Of T) Implements IEnumerable(Of T).GetEnumerator
Static iBeenCalled As Int32
If (iBeenCalled = 0) AndAlso _
(Threading.Interlocked.Increment(iBeenCalled) = 1) Then
Return Me
Else
Return New GenericIterator(Of T)(_func)
End If
End Function
Public ReadOnly Property Current() As T Implements IEnumerator(Of T).Current
Get
Return _Current
End Get
End Property
Public Overridable Sub Reset() Implements IEnumerator.Reset
Throw New NotImplementedException("Iterator cannot be reset")
End Sub
Private Function IEnumerator_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
Return Me.GetEnumerator
End Function
Private ReadOnly Property IEnumerator_Current() As Object Implements IEnumerator.Current
Get
Return Me.Current
End Get
End Property
Public Sub Dispose() Implements IDisposable.Dispose
' not implemented
End Sub
End Class
Once you have this class you can implement 'yield' similar to how it's done in this sample Zip extension function:
Public Module IEnumerableExtensions
<Extension()>
Public Function Zip(Of T1, T2)(ByVal left As IEnumerable(Of T1), ByVal right As IEnumerable(Of T2)) As IEnumerable(Of Pair(Of T1, T2))
Dim leftG As IEnumerator(Of T1) = left.Select(Function(x) x).GetEnumerator()
Dim rightG As IEnumerator(Of T2) = right.Select(Function(x) x).GetEnumerator()
Return New GenericIterator(Of Pair(Of T1, T2)) _
(Function(ByRef x) As Boolean
Dim canMove As Boolean = leftG.MoveNext() AndAlso rightG.MoveNext()
x = New Pair(Of T1, T2)(leftG.Current, rightG.Current)
Return canMove
End Function)
End Function
End Module
The lambda function has a single by ref parameter which you are supposed to save your return value to.
It is worth noting that I called the selects on leftG and rightG because the compiler was complaining about how some IEumerables like {"foo", "bar"} had already materialized. The select calls naturally removed the materialization.
It is also worth noting that for the extension function to work properly you need to import System.Runtime.CompilerServices. For the Iterator you need System.Collections.Generic. And in general you obviously need System.Linq.
It is also worth noting that in the above function 'Pair' is:
Public Class Pair(Of T1, T2)
Public Property First As T1
Public Property Second As T2
Public Sub New(ByVal f As T1, ByVal s As T2)
First = f
Second = s
End Sub
End Class
I hope this helps your conversion efforts in some way! Good luck!