Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
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 we are already at the end then return false
        If Me._Index = Me._Thing.GetUpperBound(0) Then
            Return False
        End If
        'Otherwise move to the next position in the array
        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
Posted 20-Feb-13 19:53pm

1 solution

Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

If anyone ever stumbles into this then I ended up answering my own question, yes yield is a very quick and easy shortcut to writing your own enumerator and in the majority of cases is probably at least as effective. The compiler simply turns yield into very similar code to that which it creates if you write the enumerator, so 'under the hood' there is very little difference, except possibly in specific cases or when every millisecond counts perhaps (in which case you'd probably be writing your own assembler anyway).
 
Pick Your Enumerator & Me.Understand Yield and IEnumerable (C#)[^]
Pick Your Enumerator & Me.Understand Yield and IEnumerable (VB)[^]
 
Mike
  Permalink  

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
0 Schatak 394
1 OriginalGriff 340
2 _Amy 115
3 Abhijit Ghosh (Subho) 115
4 Andreas Gieriet 100
0 OriginalGriff 7,107
1 Sergey Alexandrovich Kryukov 5,623
2 Maciej Los 3,504
3 Peter Leow 3,373
4 DamithSL 2,505


Advertise | Privacy | Mobile
Web03 | 2.8.140721.1 | Last Updated 18 Aug 2013
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100