迭代器功能错过理解概念

时间:2015-02-17 20:27:22

标签: .net vb.net function collections iterator

如果我没有弄错的话,Iterator函数可以更快地构建集合,因为它会记住添加最后一项的索引。

现在,有没有办法访问正在构建的集合?

例如,假设我需要在产生新元素之前确定集合是否包含元素,就像这样(一个非常糟糕的例子):

Public Iterator Function MyFunc(Byval param1 As whatever) As IEnumerable(Of whatever)

    For value As Integer = 0 to whatever

        If Not THE_ITERATOR_COLLECTION.Contains(whatever)
           Yield value
        End If

    End For

End Function

这可能吗?

1 个答案:

答案 0 :(得分:1)

  

,您无法在设计时访问自动生成的迭代器。

Iterator关键字提供了一种快速简便的方法来创建迭代器而无需实际创建迭代器。它由编译器创建(基于迭代器函数/属性),因此在设计时不可用。您要创建自定义迭代器或重新考虑您的设计。

看看这个简单的迭代器函数。

Public Iterator Function Foo() As IEnumerable(Of Char)
    Yield "H"c
    Yield "E"c
    Yield "L"c
    Yield "L"c
    Yield "O"c
End Function

将上述函数编译成如下所示的函数。自动生成的迭代器的类型名为 VB $ StateMachine_0_Foo

Public Function Foo() As IEnumerable(Of Char)
    Dim $sm As New VB$StateMachine_0_Foo
    $sm.$VB$Me = Me
    $sm.$State = -2
    Return $sm
End Function

迭代器的内部工作没有什么特别之处。它的工作方式与任何其他精心设计的迭代器相同。

<CompilerGenerated> _
Private NotInheritable Class VB$StateMachine_0_Foo
    Implements IDisposable, IEnumerator, IEnumerator(Of Char), IEnumerable, IEnumerable(Of Char)

    <DebuggerNonUserCode> _
    Private Overrides Function GetEnumerator() As IEnumerator(Of Char) Implements IEnumerable(Of Char).GetEnumerator
        If ((Thread.CurrentThread.ManagedThreadId = Me.$InitialThreadId) AndAlso (Me.$State = -2)) Then
            Me.$State = -1
            Return Me
        End If
        Dim foo As New VB$StateMachine_0_Foo
        foo.$VB$Me = Me.$VB$Me
        Return foo
    End Function

    <DebuggerNonUserCode> _
    Private Overrides Function GetEnumerator0() As IEnumerator Implements IEnumerable.GetEnumerator
        Return Me.GetEnumerator
    End Function

    <CompilerGenerated> _
    Friend Overrides Function MoveNext() As Boolean Implements IEnumerator.MoveNext
        Dim VB$doFinallyBodies As Boolean = True
        Try
            Select Case Me.$State
                Case 0
                    If Not Me.$Disposing Then
                        GoTo Label_0066
                    End If
                    Return False
                Case 1
                    If Not Me.$Disposing Then
                        GoTo Label_0099
                    End If
                    Return False
                Case 2
                    If Not Me.$Disposing Then
                        GoTo Label_00CC
                    End If
                    Return False
                Case 3
                    If Not Me.$Disposing Then
                        GoTo Label_00F9
                    End If
                    Return False
                Case 4
                    If Not Me.$Disposing Then
                        GoTo Label_0126
                    End If
                    Return False
                Case 5
                    Exit Select
                Case Else
                    If Not Me.$Disposing Then
                        GoTo Label_0039
                    End If
                    Exit Select
            End Select
            Return False
Label_0039:
            Me.$Current = "H"c
            Me.$State = 0
            VB$ doFinallyBodies = False
            Return True
Label_0066:
            Me.$State = -1
            Me.$Current = "E"c
            Me.$State = 1
            VB$ doFinallyBodies = False
            Return True
Label_0099:
            Me.$State = -1
            Me.$Current = "L"c
            Me.$State = 2
            VB$ doFinallyBodies = False
            Return True
Label_00CC:
            Me.$State = -1
            Me.$Current = "L"c
            Me.$State = 3
            VB$ doFinallyBodies = False
            Return True
Label_00F9:
            Me.$State = -1
            Me.$Current = "O"c
            Me.$State = 4
            VB$ doFinallyBodies = False
            Return True
Label_0126:
            Me.$State = -1
        Catch exception1 As Exception
            ProjectData.SetProjectError(exception1)
            Dim $ex As Exception = exception1
            Me.$State = 5
            Throw
            ProjectData.ClearProjectError()
        End Try
        Me.$State = 5
        Return False
    End Function

    <DebuggerNonUserCode> _
    Private Overrides Sub System.Collections.IEnumerator.Reset() Implements IEnumerator.Reset
        Throw New NotSupportedException
    End Sub

    <DebuggerNonUserCode> _
    Private Overrides Sub System.IDisposable.Dispose() Implements IDisposable.Dispose
        Me.$Disposing = True
        Me.MoveNext()
        Me.$State = 5
    End Sub

    Private Overrides ReadOnly Property System.Collections.Generic.IEnumerator(Of Char).Current As Char
        <DebuggerNonUserCode> _
        Get
            Return Me.$Current
        End Get
    End Property

    Private Overrides ReadOnly Property System.Collections.IEnumerator.Current As Object
        <DebuggerNonUserCode> _
        Get
            Return Me.$Current
        End Get
    End Property

    Friend $Current As Char
    Friend $Disposing As Boolean
    Friend $InitialThreadId As Integer = Thread.CurrentThread.ManagedThreadId
    Friend $State As Integer = -1
    Friend $VB$Me As Form1

End Class

相关参考资料: