是否可以使用GoTo?

时间:2010-07-07 15:24:28

标签: c# vb6 label goto

我目前正在.Net Framework 2.0中用C#重写一个旧的VB6程序(不是我的选择,它是由公司决定的)。在大多数情况下,事情进展顺利。该程序测量来自精密磨床的输入数据,并显示图形和刻度盘以显示精度。

原始程序员是机械工程师,但不是软件工程师。该程序有效,但这里和那里有一些草率的代码。最值得注意的是,我遇到了一些GoTo语句。在必要时将事物放在一个循环中并且从中获得相同的功能非常容易。

我遇到了原始代码中的一个案例,然而,似乎GoTo不仅仅是模拟一个循环。它有几个不同的退出条件。它看起来像这样(不是实际代码,只是我做的简短演示):

VB6代码

Public Sub Tick()
    Dim condition1 As Boolean
    Dim condition2 As Boolean
    Dim testNumber As Integer

    beginning:    'The GoTo label'

    ' (... Some Other Code Here ...)'

    If condition1 = True Then
        goto beginning
    Else
        ' (... Do some calculation ...)'
    End If

    If condition2 = True Then
        ' (... Do some calculation ...)'
        goto beginning
    End If

    Select Case testNumber
        Case 1: '(... Some code ...)'
        Case 2: '(... Some code ...)'
        Case 3: '(... Some code ...)'
        Case 4: goto beginning
    End Select
End Sub

实际的代码可能比这个条件少一些,但基本的想法是有一些不同的东西导致它循环回来。是否有一种很好的方法可以为这种情况编写一个循环,或者这是一个goto语句可以接受的情况? (不可否认,非goto解决方案将是首选)。

感谢您的时间和考虑。

注意:我尝试使用while(true)循环中断;声明,但它导致程序陷入无限循环并锁定。是否会建议写一个包含几个条件的长时间循环(用和/或等)?

6 个答案:

答案 0 :(得分:6)

while(true)循环应该没问题,如果你在它的末尾有一个休息时间,并且continue在以前有过goto的地方。然而,这绝对应该只是第一步 - 听起来需要一个强有力的重构。

答案 1 :(得分:1)

首先将该循环的主体放入一个单独的函数中,然后用`return'替换goto - 或者将几个单独的函数取代:

If condition1 = True Then 
    goto beginning 
Else 
    ' (... Do some calculation ...)' 
End If 

应该成为

If not condition1
      DoSomeCalculation()
End If

很快关于什么时候循环的逻辑&何时退出将出现。当发生这种情况时,重构此代码应该变得像您已经完成的那样微不足道。

答案 2 :(得分:1)

我认为您的第一步应该是将所有'(do some code)'提取到自己的方法中。一旦你完成了,实际的代码流将变得更加清晰。

根据它的嵌套方式,有几种可能的方法可以实现这一点(没有实际代码)很难。

(我是C#编码员,我不知道VB,请原谅)

递归

Public Sub Tick()
    Dim condition1 As Boolean
    Dim condition2 As Boolean
    Dim testNumber As Integer

    If basecase = True Then
       return;
    EndIf

    ExecuteInitialzerStuff();

    If intialized = False Then
        Tick();
        return;
    Else
        ExecuteAffirmationStuff();
    End If

    If affirmed = True Then
        ExecutePostAffirm();
        Tick();
        return;
    End If

    Select Case testNumber
        Case 4: Tick();
    End Select
End Sub

另一种选择是将每个选项分解为离散代码流

Public Sub Tick()
    Dim condition1 As Boolean
    Dim condition2 As Boolean
    Dim testNumber As Integer

    If condition1 = true Then
       Tick_Condition1();
       return;
    EndIf

    If condition2 = true Then
       Tick_Condition2();
       return;
    EndIf

    Tick_Switch(testNumber);

一旦你分解了每个代码部分试图完成的每个单独任务,就应该清楚这个方法应该被完全删除,并分成几个单独的Tick()方法,每个方法都被调用TickInit() TickDestroy(), TickSkyFalling();或其他什么,视情况而定。

我认为尝试重构这个功能是错误的决定。但是如果没有看到实际的代码我就无法确定。

答案 3 :(得分:1)

在switch语句中:

        switch (groupMembershipStatus)
        {
            case SocialGroupMembershipStatus.Banned:
                return redirect();
            case SocialGroupMembershipStatus.MembershipRequestDenied:
                Abc();
                goto case SocialGroupMembershipStatus.Banned;
        }

(正如你所看到的,我刚刚在生产代码中写了一个goto,我想知道是否存在关于goto使用的C#问题!)

答案 4 :(得分:0)

我将它包装在一个单元测试中并通过它发出各种值并记录结果。

然后,当您将代码重构为C#时,您可以使用测试结果来验证您的操作。

答案 5 :(得分:0)

虽然这个案例对于do / while true循环看起来很好,但我看到一些不是这样的情况。

在词法分析者或其他FSA机制之外,根据我的判断,每2000行不止一个goto意味着你做错了什么。

当然,如果你有一个反复出现的成语,这是另一个故事,因为反复出现的习语会覆盖风格规则。成语=一致,一致=可读。