VB.NET 中的 GoTo 语句和替代方案
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2700531/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
GoTo statements and alternatives in VB.NET
提问by qais
I've posted a code snippet on another forum asking for help and people pointed out to me that using GoTo
statements is very bad programming practice. I'm wondering: why is it bad?
我在另一个论坛上发布了一个代码片段寻求帮助,人们向我指出使用GoTo
语句是非常糟糕的编程实践。我想知道:为什么不好?
What alternatives to GoTo
are there to use in VB.NET that would be considered generally more of a better practice?
GoTo
在 VB.NET 中使用哪些替代方案通常被认为是更好的做法?
Consider this snippet below where the user has to input their date of birth. If the month/date/year are invalid or unrealistic, I'd like to loop back and ask the user again. (I'm using if statements to check the integer's size... if there's a better way to do this, I'd appreciate if you could tell me that also :D)
考虑下面的这个片段,用户必须输入他们的出生日期。如果月/日/年无效或不切实际,我想回过头来再次询问用户。(我正在使用 if 语句来检查整数的大小......如果有更好的方法来做到这一点,如果你也能告诉我,我将不胜感激:D)
retryday:
Console.WriteLine("Please enter the day you were born : ")
day = Console.ReadLine
If day > 31 Or day < 1 Then
Console.WriteLine("Please enter a valid day")
GoTo retryday
End If
回答by Earlz
I'm going to differ from everyone else and say that GOTOs themselves are not all the evil. The evil comes from the misuse of GOTO.
我将与其他人不同,并说 GOTO 本身并不都是邪恶的。邪恶来自对GOTO的滥用。
In general, there is almost always better solutions than using a GOTO, but there really are times when GOTO is the proper way to do it.
一般而言,几乎总是有比使用 GOTO 更好的解决方案,但确实有时 GOTO 是正确的方法。
That being said, you are a beginner, so you shouldn't be allowed to judge if GOTO is proper or not (because it hardly ever is) for a few more years.
话虽如此,你是一个初学者,所以你不应该被允许在几年内判断 GOTO 是否正确(因为它几乎从来没有)。
I would write your code like this (my VB is a bit rusty...):
我会这样写你的代码(我的VB有点生疏......):
Dim valid As Boolean = False
While Not valid
Console.WriteLine("Please enter the day you were born: ")
Dim day As String
day = Console.ReadLine
If day > 31 Or day < 1 Then
Console.WriteLine("Please enter a valid day.")
Else
valid = True
End If
End While
If you take your GOTO code and look at it, how would someone first approach your code? "Hmm.. retryday? What does this do? When does this happen? Oh, so we goto that label if the day is out of range. Ok, so we want to loop until the date is considered to be valid and in range".
如果您拿起 GOTO 代码并查看它,那么首先有人会如何处理您的代码?“嗯..重试日?这是做什么的?什么时候发生?哦,所以如果日期超出范围,我们就会转到那个标签。好的,所以我们想循环直到日期被认为是有效的并且在范围内” .
Whereas if you look at mine:
而如果你看看我的:
"Oh, we want to keep doing this until it's Valid. It is valid when the date is within range."
“哦,我们想一直这样做,直到它有效。当日期在范围内时,它才有效。”
回答by Andy
http://xkcd.com/292/I think this is the standard opinion of GoTo
.
http://xkcd.com/292/我认为这是GoTo
.
Instead, try and use a Do Until
loop. Do Until
loops will always execute once and are great when you need to prompt the user and want to make sure that you do not proceed until they enter the correct information.
相反,尝试使用Do Until
循环。Do Until
循环将始终执行一次,并且在您需要提示用户并希望确保在他们输入正确信息之前不要继续时非常有用。
Sub Main()
'Every time the loop runs, this variable will tell whether
'the user has finally entered a proper value.
Dim Valid As Boolean = False
'This is the variable which stores the final number which user enters.
Dim Day As Integer = 0
Do Until Valid
Console.WriteLine("Enter the day:")
Dim DayStr As String = Console.ReadLine()
If Not Integer.TryParse(DayStr, Day) Then
Console.WriteLine("Invalid value! It must be a valid number.")
Valid = False
ElseIf (Day < 1) Or (Day > 31) Then
onsole.WriteLine("Invalid day! It must be from 1 to 31.")
Valid = False
Else
Valid = True
End If
Loop
'blablabla
'Do whatever you want, with the Day variable
End Sub
回答by mjv
Questions about the merits of the GoTo
statement (or rather the lack thereof) are perennial on this site. Click here for an example: Is GoTo still considered harmful?
关于该GoTo
声明的优点(或者更确切地说是缺乏)的问题在本网站上长期存在。单击此处查看示例: GoTo 仍然被认为是有害的吗?
With regards to an alternative to GoTo
, in the provided snippet, a while
loop would nicely do the trick, maybe something like:
关于 的替代方案GoTo
,在提供的代码段中,while
循环可以很好地解决问题,可能类似于:
day = -1
While (day < 0)
Console.WriteLine("Please enter the day you were born : ")
day = Console.ReadLine
If day > 31 Or day < 1 Then
Console.WriteLine("Please enter a valid day")
day = -1
End If
End While
回答by Raj More
The GOTO
construct produces sphagetti code. This makes tracing through code almost impossible.
该GOTO
构造产生 sphagetti 代码。这使得通过代码进行跟踪几乎是不可能的。
Procedural / Functional programming is a much better approach.
过程/函数式编程是一种更好的方法。
回答by brydgesk
GOTOs are a pretty political issue. The 'solution' to GOTOs is to use other built-in navigation constructs like functions, methods, loops, etc. For VB, you could make a sub-procedure that runs that code, or put it in a While loop. You can google both of those subjects fairly easily.
GOTO 是一个相当化的问题。GOTO 的“解决方案”是使用其他内置导航结构,如函数、方法、循环等。对于 VB,您可以创建一个运行该代码的子过程,或将其放入 While 循环中。你可以很容易地用谷歌搜索这两个主题。
回答by Jeremy
A little clunky but:
有点笨重,但是:
Dim bContinue As Boolean
Console.WriteLine("Enter a number between 1 and 31")
Do
Dim number As Integer = Console.ReadLine()
If number >= 1 AndAlso number <= 31 Then
bContinue = True
Else
Console.WriteLine("Please enter a VALID number between 1 and 31")
End If
Loop Until bContinue
Also consider some basic loops in "goto land"
还要考虑“goto land”中的一些基本循环
Dim i As Integer
startofloop1:
Debug.WriteLine(i)
i += 1
If i <= 10 Then
GoTo startofloop1
End If
i = 0
startofloop2:
Debug.WriteLine(i * 2)
i += 1
If i <= 10 Then
GoTo startofloop2
End If
Here's the nice equivalent:
这是很好的等价物:
For x As Integer = 0 To 10
Debug.WriteLine(i)
Next
For x As Integer = 0 To 10
Debug.WriteLine(i * 2)
Next
Which is more readable and less error prone?
哪个更易读且不易出错?
回答by Qwertie
Using goto has been considered a bad practice for decades now. Perhaps it was a backlash against the original BASIC (before Visual Basic). In the original BASIC there were no while loops, no local variables (only globals), and (in most BASIC versions) functions could not take parameters or return values. Moreover, functions were not explicitly separated; control can implicitly fell from one function to another if you forgot a RETURN statement. Finally, code indentation was a foreign concept in these early BASICs.
几十年来,使用 goto 一直被认为是一种不好的做法。也许这是对原始 BASIC(在 Visual Basic 之前)的强烈反对。在最初的 BASIC 中,没有 while 循环,没有局部变量(只有全局变量),并且(在大多数 BASIC 版本中)函数不能接受参数或返回值。此外,功能没有明确分离;如果您忘记了 RETURN 语句,则控制可能会隐式地从一个函数下降到另一个函数。最后,代码缩进在这些早期的 BASIC 中是一个陌生的概念。
If you used the original BASIC for a some time (like I did), you would come to appreciate how the use of global variables and gotos everywhere makes a large program hard to understand, and without great care, turned it into a tangled mess of "spaghetti". When I learned QBASIC, with its WHILE..WEND loops and SUBs, I never looked back.
如果您使用原始 BASIC 一段时间(就像我一样),您会明白如何使用全局变量和 gotos 使大型程序难以理解,并且不加注意地将其变成一团乱麻“意大利面”。当我学习 QBASIC 及其 WHILE..WEND 循环和 SUB 时,我从未回头。
I don't think gotos hurt in small quantities, but in the coder culture a strong sense lingers that they are somehow evil. Therefore, I would avoid gotos for no other reason than to avoid offending sensibilities. Occasionally I find that a goto solves a problem cleanly (like breaking out of an outer loop from within an inner loop), but you should consider whether another solution makes the code more readable (e.g. put the outer loop in a separate function and use "exit function", instead of goto, in the inner loop).
我不认为 goto 会受到少量伤害,但在程序员文化中,强烈的感觉挥之不去,他们在某种程度上是邪恶的。因此,我会避免使用 goto,只是为了避免冒犯他人的敏感性。有时我发现 goto 可以干净利落地解决问题(例如从内循环中跳出外循环),但您应该考虑是否有其他解决方案使代码更具可读性(例如,将外循环放在单独的函数中并使用“退出函数”,而不是内部循环中的 goto)。
I wrote a C++ program with perhaps 100,000 lines of code and I've used goto 30 times. Meanwhile, there are more than 1,000 "normal" loops and around 10,000 "if" statements.
我用大约 100,000 行代码编写了一个 C++ 程序,并且我已经使用了 30 次 goto。同时,有 1,000 多个“正常”循环和大约 10,000 个“if”语句。
回答by Jeff B
Functions FTW!
功能 FTW!
Okay, I'm not sure if your code is really VB.Net here, since you've got some wonky type stuff going on (i.e. Console.Readline
returns a String
, not a number you can do comparisons on)... so we'll just forget about type for the moment.
好吧,我不确定你的代码是否真的是 VB.Net,因为你有一些奇怪的类型的东西(即Console.Readline
返回 a String
,而不是你可以进行比较的数字)......所以我们只会暂时忘记类型。
Console.Writeline("Please enter the day you were born : ")
day = Console.Readline()
While not ValidDate(day)
Console.WriteLine("Please enter a valid day")
day = Console.Readline()
End While
And separately
并分别
Function ValidDate(day) As Boolean
Return day > 31 Or day < 1
End Function
Or you could have fun with recursion and early-return syntax! ;)
或者你可以享受递归和提前返回语法的乐趣!;)
Function GetDate() As String
Console.Writeline("Please enter the day you were born : ")
day = Console.Readline()
If ValidDate(day) Then Return day 'Early return
Console.Writeline("Invalid date... try again")
GetDate()
End Function
回答by lauCosma
I'll throw mine even though the 'by the book' wolves outhere will downvote. Have a look at : Is it ever advantageous to use 'goto' in a language that supports loops and functions? If so, why?
即使外面的“书本”狼会投反对票,我也会投掷我的。看看:在支持循环和函数的语言中使用“goto”是否有利?如果是这样,为什么?
回答by Michael Tant
I've got to agree with everyone else here: GOTO itself is not evil, but misusing it will certainly make your life miserable. There are so many other control structures to choose from, and a well-written program can usually handle most every situation without goto. That being said, I am at the near-completion point of a program that's racking up about 15,000 lines, and I used one, and only one, GOTO statement (which I may be replacing we will see). It's the first time I've used GOTO in the last dozen or so programs I've dealt with. But in this instance it got rid of a compiler error (using Me.Close() twice within the same Sub but within different If structures; I could have suppressed it but I simply threw in a label and replaced one Me.Close() with a GoTo CloseLabel). If I start running into more instances that require Me.Close() within this Sub, I'm likely to put Me.Close() in its own sub and simply call that sub from the If structures or other loops that result in a closing of the program... As I said, there's alternatives, but sometimes, and when used very rarely, sparingly, and strategically, GoTo can still be helpful. Just beware of spaghetti code, that's a blinking mess lol
我必须同意这里的其他人:GOTO 本身并不邪恶,但滥用它肯定会让你的生活变得悲惨。有许多其他控制结构可供选择,一个编写良好的程序通常可以处理大多数情况而无需 goto。话虽如此,我正接近完成一个大约 15,000 行的程序,我使用了一个,而且只有一个 GOTO 语句(我可能会替换它,我们会看到)。这是我第一次在我处理过的大约十几个程序中使用 GOTO。但在这种情况下,它摆脱了编译器错误(在同一个 Sub 中使用 Me.Close() 两次,但在不同的 If 结构中;我可以抑制它,但我只是简单地放入一个标签并将一个 Me.Close() 替换为转到关闭标签)。如果我开始遇到更多需要我的实例。Close() 在这个 Sub 中,我很可能将 Me.Close() 放在它自己的 sub 中,然后简单地从 If 结构或其他导致程序关闭的循环中调用该 sub ......正如我所说,有替代方案,但有时,当很少使用、谨慎使用和战略性地使用时,GoTo 仍然会有所帮助。小心意大利面条代码,那是一团糟,哈哈