VBA 递归方法 - 退出函数不退出
VBA Recursion Method - Exit Function Not Exiting
为什么这个函数没有退出?我已经尝试了 Exit Function 和 Exit For。在我到达 Ubound(arr) 语句后,我重置为 i = 0 并且调用堆栈恢复为 End Select 语句,然后 For 循环再次开始。这一定是来自我执行的递归行?
Function AddArrToObj(ByRef arr As Variant, ByRef obj As Object, Optional ByVal i As Integer = 0)
For i = LBound(arr) To UBound(arr)
Select Case VBA.TypeName(obj)
Case "Collection"
obj.Add arr(i)
Case "Dictionary"
obj.Add i + 1 & " " & arr(i), arr(i)
Case "Nothing"
Set obj = New VBA.Collection
Call AddArrToObj(arr, obj) 'Recursion
End Select
'Add Watch for i = 3 break on True
'Why does this function not exit appropriately?
If Not IsEmpty(obj) And i = UBound(arr) Then Exit Function
Next i
End Function
Public Sub TestSO()
Dim collA As VBA.Collection
Dim cmdStr As String
cmdStr = "Whosebug is a website."
arr = VBA.Split(cmdStr, " ")
Call AddArrToObj(arr, collA)
End Sub
您可以使用递归来完成此操作,但它不必要地复杂。根据经验,当递归算法更易于读写时,您应该只使用递归而不是迭代。否则,由于使用递归可能会出现 Whosebug 错误,因此您应该使用迭代。话虽如此,这是一个使用递归的解决方案。我对您的代码进行了一些修改,使其既可以使用递归工作又可以遍历返回的集合对象。:
Function AddArrToObj(ByRef arr As Variant, ByRef obj As Object, Optional ByVal i As Integer = 0)
If obj Is Nothing And i <> 0 Then
Set obj = New Collection
End If
For i = LBound(arr) To UBound(arr)
Select Case VBA.TypeName(obj)
Case "Collection"
obj.Add arr(i)
Case "Dictionary"
obj.Add i + 1 & " " & arr(i), arr(i)
Case "Nothing"
Set obj = AddArrToObj(arr, obj, 1) 'Recursion
Exit For
End Select
Next i
Set AddArrToObj = obj
End Function
Public Sub TestSO()
Dim collA As VBA.Collection
Dim cmdStr As String
Dim arr() As String
Dim obj As Object
Dim elem As Variant
cmdStr = "Whosebug is a website."
arr = VBA.Split(cmdStr, " ")
Set obj = AddArrToObj(arr, collA)
For Each elem In obj
Debug.Print elem
Next elem
End Sub
为什么这个函数没有退出?我已经尝试了 Exit Function 和 Exit For。在我到达 Ubound(arr) 语句后,我重置为 i = 0 并且调用堆栈恢复为 End Select 语句,然后 For 循环再次开始。这一定是来自我执行的递归行?
Function AddArrToObj(ByRef arr As Variant, ByRef obj As Object, Optional ByVal i As Integer = 0)
For i = LBound(arr) To UBound(arr)
Select Case VBA.TypeName(obj)
Case "Collection"
obj.Add arr(i)
Case "Dictionary"
obj.Add i + 1 & " " & arr(i), arr(i)
Case "Nothing"
Set obj = New VBA.Collection
Call AddArrToObj(arr, obj) 'Recursion
End Select
'Add Watch for i = 3 break on True
'Why does this function not exit appropriately?
If Not IsEmpty(obj) And i = UBound(arr) Then Exit Function
Next i
End Function
Public Sub TestSO()
Dim collA As VBA.Collection
Dim cmdStr As String
cmdStr = "Whosebug is a website."
arr = VBA.Split(cmdStr, " ")
Call AddArrToObj(arr, collA)
End Sub
您可以使用递归来完成此操作,但它不必要地复杂。根据经验,当递归算法更易于读写时,您应该只使用递归而不是迭代。否则,由于使用递归可能会出现 Whosebug 错误,因此您应该使用迭代。话虽如此,这是一个使用递归的解决方案。我对您的代码进行了一些修改,使其既可以使用递归工作又可以遍历返回的集合对象。:
Function AddArrToObj(ByRef arr As Variant, ByRef obj As Object, Optional ByVal i As Integer = 0)
If obj Is Nothing And i <> 0 Then
Set obj = New Collection
End If
For i = LBound(arr) To UBound(arr)
Select Case VBA.TypeName(obj)
Case "Collection"
obj.Add arr(i)
Case "Dictionary"
obj.Add i + 1 & " " & arr(i), arr(i)
Case "Nothing"
Set obj = AddArrToObj(arr, obj, 1) 'Recursion
Exit For
End Select
Next i
Set AddArrToObj = obj
End Function
Public Sub TestSO()
Dim collA As VBA.Collection
Dim cmdStr As String
Dim arr() As String
Dim obj As Object
Dim elem As Variant
cmdStr = "Whosebug is a website."
arr = VBA.Split(cmdStr, " ")
Set obj = AddArrToObj(arr, collA)
For Each elem In obj
Debug.Print elem
Next elem
End Sub