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) 循环;语句,但它导致程序陷入无限循环并锁定。是否更建议编写一个包含多个条件(使用和/或等)的长 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
while(true)
循环应该没问题,如果你在它的末尾有一个中断并且在之前有 goto 的地方继续
。然而,这绝对应该只是第一步——听起来需要进行大力的重构。A
while(true)
loop should be fine, if you have a break at the end of it andcontinue
wherever there was previously a goto. However, this should definitely only be the first step - it sounds like a vigorous refactoring is called for.首先将该循环的主体放入一个单独的函数中,并用“return”替换“goto”——或者预先准备几个单独的函数:
应该很快就会成为
关于何时循环和循环的逻辑。何时退出将会出现。当这种情况发生时,重构此代码应该变得像您已经完成的那样微不足道。
Start by putting the body of that loop into a separate function, and replace the
goto
s with `return's -- or prehaps several separate functions :should become
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.
虽然这种情况对于 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.
我认为您的第一步应该是将所有
'(do some code)'
提取到它们自己的方法中。完成此操作后,实际的代码流程将变得更加清晰。根据嵌套的方式,有几种可能的方法可以实现此目的(没有实际代码很难实现)。
(我是一名 C# 编码员,我不懂 VB,请原谅)
递归的
另一个选择是将每个选项分解为离散的代码流
一旦分解了每个代码部分试图执行的每个单独的任务完成后,很可能应该清楚该方法应该被完全删除,并分成几个单独的 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
another option would be to break each option into a discrete code flow
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.
在 switch 语句中:(
如您所见,我刚刚在生产代码中编写了一个 goto,我想知道是否存在关于 goto 的使用的 C# 问题!)
In a switch-statement:
(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!)
我将其包装在单元测试中,并通过它触发各种值并记录结果。
然后,当您将代码重构为 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.