Yield in VB.NET
Solution 1:
Note: This answer is old now. Iterator blocks have since been added to VB.NET
C# translates the yield keyword into a state machine at compile time. VB.NET does not have the yield keyword, but it does have its own mechanism for safely embedding state within a function that is not easily available in C#.
The C# static
keyword is normally translated to Visual Basic using the Shared
keyword, but there are two places where things get confusing. One is that a C# static class is really a Module in Visual Basic rather than a Shared class (you'd think they'd let you code it either way in Visual Basic, but noooo). The other is that VB.NET does have its own Static
keyword. However, Static
has a different meaning in VB.NET.
You use the Static
keyword in VB.NET to declare a variable inside a function, and when you do the variable retains its state across function calls. This is different than just declaring a private static class member in C#, because a static function member in VB.NET is guaranteed to also be thread-safe, in that the compiler translates it to use the Monitor class at compile time.
So why write all this here? Well, it should be possible to build a re-usable generic Iterator<T>
class (or Iterator(Of T)
in VB.NET). In this class you would implement the state machine used by C#, with Yield()
and Break()
methods that correspond to the C# keywords. Then you could use a static instance (in the VB.NET sense) in a function so that it can ultimately do pretty much the same job as C#'s yield
in about the same amount of code (discarding the class implemenation itself, since it would be infinitely re-usable).
I haven't cared enough about Yield to attempt it myself, but it should be doable. That said, it's also far from trivial, as C# team member Eric Lippert calls this "the most complicated transformation in the compiler."
I have also come to believe since I wrote the first draft of this over a year ago that it's not really possible in a meaningful way until Visual Studio 2010 comes out, as it would require sending multiple lambdas to the Iterator class and so to be really practical we need .NET 4's support for multi-line lambdas.
Solution 2:
The Async CTP includes support for Yield
in VB.NET.
See Iterators in Visual Basic for information on usage.
And now it's included in the box with Visual Studio 2012!
Solution 3:
There's the nice article Use Iterators in VB Now by Bill McCarthy in Visual Studio Magazine on emulating yield
in VB.NET. Alternatively wait for the next version of Visual Basic.
Solution 4:
Fortunately now we have Yield
return
here is an example from my project + implementing an interface with System.Collections.Generic.IEnumerable(T)
function:
Public Class Status
Implements IStatus
Private _statusChangeDate As DateTime
Public Property statusChangeDate As DateTime Implements IStatus.statusChangeDate
Get
Return _statusChangeDate
End Get
Set(value As Date)
_statusChangeDate = value
End Set
End Property
Private _statusId As Integer
Public Property statusId As Integer Implements IStatus.statusId
Get
Return _statusId
End Get
Set(value As Integer)
_statusId = value
End Set
End Property
Private _statusName As String
Public Property statusName As String Implements IStatus.statusName
Get
Return _statusName
End Get
Set(value As String)
_statusName = value
End Set
End Property
Public Iterator Function GetEnumerator() As IEnumerable(Of Object) Implements IStatus.GetEnumerator
Yield Convert.ToDateTime(statusChangeDate)
Yield Convert.ToInt32(statusId)
Yield statusName.ToString()
End Function
End Class
Public Interface IStatus
Property statusChangeDate As DateTime
Property statusId As Integer
Property statusName As String
Function GetEnumerator() As System.Collections.Generic.IEnumerable(Of Object)
End Interface
This is how i extract all properties from outside:
For Each itm As SLA.IStatus In outputlist
For Each it As Object In itm.GetEnumerator()
Debug.Write(it & " ")
Next
Debug.WriteLine("")
Next
Solution 5:
VB.NET has the Iterator
keyword https://docs.microsoft.com/en-us/dotnet/visual-basic/language-reference/modifiers/iterator
Since Visual Studio 2012 it seems