我在c#中有一个递归函数,效果很好。但是当我将它转换为VB.Net时,它会产生索引错误。奇怪的是,当它在VB中调试时,代码进入'End Sub'行并再次进入递归函数调用。知道为什么会这样吗?
这是一个简单的功能,可以从组列表中校正生成有序年龄组。请参阅下面的代码。
最终预期组为0-10,30-60和75-90。
Public Class AgeGroup
Public Lower As Integer
Public Higher As Integer
End Class
Public Class RngTest
Public Sub MakeUniqueRanges(ByVal ranges As List(Of AgeGroup))
For i As Integer = 0 To ranges.Count - 2
Dim first As AgeGroup = ranges(i)
Dim second As AgeGroup = ranges(i + 1)
If first.Higher > second.Lower Then
'range is mixed..construct a new range by mixing the two ranges
Dim newRange As New AgeGroup()
newRange.Lower = first.Lower
newRange.Higher = second.Higher
'delete the existing 2 ranges
ranges.RemoveAt(i)
ranges.RemoveAt(i)
ranges.Insert(i, newRange)
MakeUniqueRanges(ranges)
End If
Next
End Sub
End Class
Module RngModule
Sub Main()
Dim ranges As New List(Of AgeGroup)()
ranges.Add(New AgeGroup() With {.Lower = 0, .Higher = 10})
ranges.Add(New AgeGroup() With {.Lower = 30, .Higher = 40})
ranges.Add(New AgeGroup() With {.Lower = 35, .Higher = 50})
ranges.Add(New AgeGroup() With {.Lower = 45, .Higher = 60})
ranges.Add(New AgeGroup() With {.Lower = 75, .Higher = 90})
Dim test As New RngTest()
test.MakeUniqueRanges(ranges)
Console.ReadLine()
End Sub
End Module
这是运行良好的c#方法
static void MakeUniqueRanges(List<AgeGroup> ranges)
{
for (int i = 0; i < ranges.Count - 1; i++)
{
AgeGroup first = ranges[i];
AgeGroup second = ranges[i + 1];
if (first.Higher > second.Lower)
{
//range is mixed..
AgeGroup newRange = new AgeGroup();
newRange.Lower = first.Lower;
newRange.Higher = second.Higher;
ranges.RemoveAt(i);
ranges.RemoveAt(i);
ranges.Insert(i, newRange);
MakeUniqueRanges(ranges);
}
}
}
答案 0 :(得分:4)
这是非递归的C#版本:
static void MakeUniqueRanges(List<AgeGroup> ranges)
{
for (int i = 0; i < ranges.Count - 1; i++)
{
AgeGroup first = ranges[i];
AgeGroup second = ranges[i + 1];
while (first.Higher > second.Lower)
{
//range is mixed..
AgeGroup newRange = new AgeGroup();
newRange.Lower = first.Lower;
newRange.Higher = second.Higher;
ranges.RemoveAt(i); //Remove "first"
ranges[i] = newRange; //Replace "second"
if (i == ranges.Count - 1) return; //Are we now at the end of the list?
first = ranges[i];
second = ranges[i + 1];
}
}
}
这应该是VB的等价物:
Public Sub MakeUniqueRanges(ByVal ranges As List(Of AgeGroup))
Dim i as Integer = 0
While i <= ranges.Count - 2
Dim first As AgeGroup = ranges(i)
Dim second As AgeGroup = ranges(i + 1)
While first.Higher > second.Lower
'range is mixed..construct a new range by mixing the two ranges
Dim newRange As New AgeGroup()
newRange.Lower = first.Lower
newRange.Higher = second.Higher
ranges.RemoveAt(i) 'Remove "first"
ranges(i) = newRange
If i = ranges.Count - 1 Then Return
first = ranges(i)
second = ranges(i + 1)
End While
i = i + 1
End While
End Sub
那么,为什么你原来的尝试不起作用?因为在VB中,首次启动循环时,要执行的迭代次数是固定的。每次循环都不会重新评估end
值。所以这段代码:
Dim i = 5
For j = 0 To i
i = 1
Console.WriteLine("Hello")
Next
打印Hello
6次。而在C#for
循环中,终止条件在每次循环期间都会被完全重新评估。
请参阅For...Next:
当您事先不知道在循环中运行语句的次数时,
While...End While
Statement (Visual Basic)或Do...Loop
Statement (Visual Basic)效果很好。但是,当您希望循环运行特定次数时,For...Next
循环是更好的选择。您可以确定首次进入循环时的迭代次数。
递归的原因是没有意义的?因为在此功能实际返回的任何时候,它已经在整个列表中运行了。你不应该以递归方式调用函数,然后再继续在列表中工作。
当你进行递归调用时,你强制它在列表的开头再次启动,你当前的调用已经检查过了。