GoTo 的使用是否可接受?

发布于 2024-09-08 16:22:14 字数 1177 浏览 12 评论 0原文

我目前正在.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) 循环;语句,但它导致程序陷入无限循环并锁定。是否更建议编写一个包含多个条件(使用和/或等)的长 while 循环?

I'm currently rewriting an old VB6 program in C# in the .Net Framework 2.0 (not my choice, it was decided by the company). For the most part, things have gone pretty well. The program measures incoming data from a precision grinding machine and displays graphs and dials to display the accuracy.

The original programmer was a mechanical engineer, however, not a software engineer. The program works, but there's a bit of sloppy code here and there. Most notably, I've run into a few GoTo statements. It's been pretty easy to just stick things in a loop, where necessary, and get the same functionality out of it.

I've run up against a case in the original code, however, where it seems like the GoTo is doing more than just simulating a loop. It has a couple different exit conditions. It looks something like this (not the actual code, just something short I made up to demonstrate):

VB6 Code

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

The actual code might have a few less conditions than that, but the basic idea is that there are a few different things that cause it to loop back on itself. Is there a good way to go about writing a loop for a situation like that, or is this a case in which a goto statement would be acceptable? (Admittedly, a non-goto solution would be preferred).

Thanks for your time and consideration.

Note: I tried using a while(true) loop with a break; statement, but it caused the program to get caught in an infinite loop and lock up. Would it be more advised to write a long while loop containing several conditions (with and/or, etc.)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

泡沫很甜 2024-09-15 16:22:14

while(true) 循环应该没问题,如果你在它的末尾有一个中断并且在之前有 goto 的地方继续。然而,这绝对应该只是第一步——听起来需要进行大力的重构。

A while(true) loop should be fine, if you have a break at the end of it and continue wherever there was previously a goto. However, this should definitely only be the first step - it sounds like a vigorous refactoring is called for.

﹏半生如梦愿梦如真 2024-09-15 16:22:14

首先将该循环的主体放入一个单独的函数中,并用“return”替换“goto”——或者预先准备几个单独的函数:

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

应该很快就会成为

If not condition1
      DoSomeCalculation()
End If

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

Start by putting the body of that loop into a separate function, and replace the gotos with `return's -- or prehaps several separate functions :

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

should become

If not condition1
      DoSomeCalculation()
End If

Soon the logic on when to loop & when to exit will emerge. When that happens, refactoring this code should become as trivial as what you've already done.

傲性难收 2024-09-15 16:22:14

虽然这种情况对于 do/while true 循环来说看起来足够好,但我也见过一些情况并非如此。

在词法分析器或其他 FSA 机制之外,我的判断是,每 2000 行超过 1 个 goto 意味着您做错了什么。

当然,如果您有一个带有 goto 的重复出现的习语,那就是另一回事了,因为重复出现的习语会覆盖样式规则。习语=一致,一致=可读。

While this case looks good enough for a do/while true loop I've seen some cases that aren't.

Outside of a lexer or other FSA mechanism, it is my judgement that more than one goto per 2000 lines means you're doing something wrong.

Of course, if you have a recurring idiom that has a goto that's another story as recurring idioms override style rules. Idiom = consistent, consistent = readable.

眼前雾蒙蒙 2024-09-15 16:22:14

我认为您的第一步应该是将所有 '(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(); 或其他,视情况而定。

我认为尝试重构这个函数是错误的决定。但在没有看到实际代码的情况下我无法确定。

I think your first step should be extracting all the '(do some code)' into their own methods. Once you've done that, the actually code flow will become a little clearer.

Depending on how nested it is, there are a few possible ways to accomplish this (hard without actual code).

(I'm a C# coder, I don't know VB, forgiveness please)

Recursive

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

another option would be to break each option into a discrete code flow

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);

Once you've broken down each of the separate tasks that each code section is trying to accomplish, it should probably become clear that this method should be deleted entirely, and split up into a few separate Tick() methods, each called TickInit() TickDestroy(), TickSkyFalling(); or whatever, depending on the situation.

I believe that trying to refactor this function in place is the wrong decision. But I can't be certain without seeing the actual code.

一曲琵琶半遮面シ 2024-09-15 16:22:14

在 switch 语句中:(

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

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

In a switch-statement:

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

(As you can see I just wrote a goto in production code and I was wondering if there is a C# question about this use of goto!)

如何视而不见 2024-09-15 16:22:14

我将其包装在单元测试中,并通过它触发各种值并记录结果。

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

I'd wrap it in a unit test and fire various values through it and record what the results are.

Then as you refactor the code into C# you can use the results of the test to verify your actions.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文