|
OK, I cannot get my head around the whether there is a difference between the 'classic' (perhaps long winded) way of doing it, multiple classes and the 'new' Yield route to (apparently) the same end.
I can understand the classic route (I think), see the code below.
Yield confuses the heck out of me, if I understand it correctly then it's absolutely genius, I get the idea of a state machine (I think) and logically it sort of makes sense but I am not at all confident.
Can it possibly be this simple? You just make that one method as simple or complex as necessary for your situation?
(Warning, silly example since arrays can already be enumerated, but it's easy to demo)
Public Class YieldExample
Implements IEnumerable
Private _Thing As Double()
Public Iterator Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
If IsNothing(Me._Thing) Then
Throw New InvalidOperationException()
End If
For Index As Integer = 0 To Me._Thing.GetUpperBound(0)
Yield Me._Thing(Index)
Next
End Function
End Class
What I understand to be the 'old way'.
Public Class ExampleEnumerable
Implements IEnumerable(Of Double)
Private _Thing As Double()
Public Function GetEnumerator() As IEnumerator(Of Double) Implements IEnumerable(Of Double).GetEnumerator
Return New ExampleEnumerator(Me._Thing)
End Function
Public Function GetEnumerator1() As IEnumerator Implements IEnumerable.GetEnumerator
Return Me.GetEnumerator
End Function
End Class
Public Class ExampleEnumerator
Implements IEnumerator(Of Double)
Private _Thing As Double()
Private _Index As Integer
Private _curItem As Double
Public Sub New(ByVal Thing As Double())
Me._Thing = Thing
Me._Index = -1
Me._curItem = Nothing
End Sub
Public ReadOnly Property Current As Double Implements IEnumerator(Of Double).Current
Get
If IsNothing(Me._curItem) Then
Throw New InvalidOperationException()
End If
Return Me._curItem
End Get
End Property
Public ReadOnly Property Current1 As Object Implements IEnumerator.Current
Get
Return Me.Current
End Get
End Property
Public Function MoveNext() As Boolean Implements IEnumerator.MoveNext
If Me._Index = Me._Thing.GetUpperBound(0) Then
Return False
End If
Me._Index += 1
Me._curItem = Me._Thing(Me._Index)
Return True
End Function
Public Sub Reset() Implements IEnumerator.Reset
Me._Index = -1
Me._curItem = Nothing
End Sub
#Region "IDisposable Support"
End Class
Thanks,
Mike
|
|
|
|
|
Dear Mike,
I realise this is a late answer, so maybe you've already figured this out. But maybe it's still worth something, so here goes:
I think the short answer is that Yield is absolutely genius. The 'classic' way as you put it actually is the same implementation over and over again, where only the return value varies. What yield does for you is that it allows you to construct an IEnumerable directly from a function (using Yield statements), such that every time MoveNext() is called, the function takes off where it left off until the next Yield statement.
So, yes, you can just use yield whenever you want I think the only possible issue with it is that it's probably slower than a proper custom ('classic') implementation, so if you have A LOT of elements AND you notice a performance bottleneck in enumeration THEN you might consider getting your hands dirty.
Best regards,
Richard
|
|
|
|
|
Thank you
Appreciated whatever the timing
|
|
|
|