VB.Net递归问题

时间:2014-05-02 09:28:31

标签: c# vb.net recursion

我在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);
        }
    }
}

1 个答案:

答案 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循环是更好的选择。您可以确定首次进入循环时的迭代次数。


递归的原因是没有意义的?因为在此功能实际返回的任何时候,它已经在整个列表中运行了。你不应该以递归方式调用函数,然后再继续在列表中工作。

当你进行递归调用时,你强制它在列表的开头再次启动,你当前的调用已经检查过了。