You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 4.0中Iterator/Yield等效实现方案咨询(VS2010兼容)

.NET 4.0下VB迭代器(Iterator/Yield)的替代实现

VB的Iterator修饰符和Yield关键字是VB 11(对应Visual Studio 2012)才新增的特性,VS2010(VB 10)和.NET Framework 4.0不支持这些语法,所以需要手动实现迭代器逻辑来替代。以下是两种可行的解决方案:

方案1:手动实现延迟加载迭代器(与原Yield行为一致)

这种方式完全模拟原代码的延迟加载特性,仅在遍历到节点时才生成对应实例,适合节点数量较多的场景,避免一次性占用过多内存。我们通过栈来处理递归遍历逻辑,实现IEnumerable(Of Node)和IEnumerator(Of Node)接口:

Private Shared Function AllNodes(ByVal nodes As NodeCollection) As IEnumerable(Of Node)
    Return New NodeEnumerable(nodes)
End Function

Private Class NodeEnumerable
    Implements IEnumerable(Of Node)
    Private ReadOnly _rootNodes As NodeCollection

    Public Sub New(rootNodes As NodeCollection)
        _rootNodes = rootNodes
    End Sub

    Public Function GetEnumerator() As IEnumerator(Of Node) Implements IEnumerable(Of Node).GetEnumerator
        Return New NodeEnumerator(_rootNodes)
    End Function

    Private Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
        Return GetEnumerator()
    End Function
End Class

Private Class NodeEnumerator
    Implements IEnumerator(Of Node)
    Private ReadOnly _stack As Stack(Of IEnumerator(Of Node))
    Private _current As Node

    Public Sub New(rootNodes As NodeCollection)
        _stack = New Stack(Of IEnumerator(Of Node))()
        _stack.Push(rootNodes.GetEnumerator())
    End Sub

    Public ReadOnly Property Current As Node Implements IEnumerator(Of Node).Current
        Get
            Return _current
        End Get
    End Property

    Private ReadOnly Property IEnumerator_Current As Object Implements IEnumerator.Current
        Get
            Return Current
        End Get
    End Property

    Public Function MoveNext() As Boolean Implements IEnumerator.MoveNext
        Do While _stack.Count > 0
            Dim currentEnumerator = _stack.Peek()
            If currentEnumerator.MoveNext() Then
                _current = DirectCast(currentEnumerator.Current, Node)
                ' 先压入子节点枚举器,保证先返回当前节点,再遍历子节点
                If _current.Nodes.Count > 0 Then
                    _stack.Push(_current.Nodes.GetEnumerator())
                End If
                Return True
            Else
                ' 当前枚举器遍历完成,释放并弹出
                currentEnumerator.Dispose()
                _stack.Pop()
            End If
        Loop
        Return False
    End Function

    Public Sub Reset() Implements IEnumerator.Reset
        Throw New NotSupportedException("Reset操作不被支持")
    End Sub

    Public Sub Dispose() Implements IDisposable.Dispose
        ' 释放所有栈中剩余的枚举器
        While _stack.Count > 0
            Dim enumerator = _stack.Pop()
            enumerator.Dispose()
        End While
    End Sub
End Class

方案2:预收集所有节点(实现简单,非延迟加载)

如果你的节点数量不多,不需要延迟加载,可以直接递归收集所有节点到列表中,实现起来更简单:

Private Shared Function AllNodes(ByVal nodes As NodeCollection) As IEnumerable(Of Node)
    Dim nodeList As New List(Of Node)()
    For Each node As Node In nodes
        nodeList.Add(node)
        ' 递归添加子节点
        If node.Nodes.Count > 0 Then
            nodeList.AddRange(AllNodes(node.Nodes))
        End If
    Next
    Return nodeList
End Function

注意事项

  • 方案1的延迟加载特性和原Yield代码完全一致,遍历过程中才会逐个生成节点,适合大数据量场景。
  • 方案2会一次性把所有节点加载到内存中,实现成本低,但内存占用较高,适合小数据量场景。

内容的提问来源于stack exchange,提问作者Frank Holloway

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 22:55:18