做一些研制后如何通过二次回路断线
while (true) { // Main Loop
for (int I = 0; I < 15; I++) { // Secondary loop
// Do Something
break; // Break main loop?
}
}
大多数人建议称之为“转到”功能
展望如下面的例子:
while (true) { // Main Loop
for (int I = 0; I < 15; I++) { // Secondary Loop
// Do Something
goto ContinueOn; // Breaks the main loop
}
}
ContinueOn:
然而; 我经常听说“转到”语句是不好的做法。 下面的图片是完全说明我的观点:
所以
- 有多糟糕goto语句真的,为什么?
- 有没有打破主循环比使用“转到”语句更有效的方式?
编辑:
有多糟糕goto语句真的,为什么?
这要看具体情况。 我不记得任何时候,我发现它使代码重构相比更具可读性。 这也取决于可读性的个人观点 - 有些人不喜欢比别人多,因为从其他的答案清晰。 ( -有效地都在C#5异步/ AWAIT代码是基于大量的goto方法的作为关注点,它广泛用于生成的代码)。
问题是,那里的情况下goto
一般用往往是那种情况下无论如何重构艾滋病的事情-而goto
与越来越难以遵循代码变得更复杂的解决方案棒。
有没有打破主循环比使用“转到”语句更有效的方式?
绝对。 提取你的方法到一个单独的功能:
while (ProcessValues(...))
{
// Body left deliberately empty
}
...
private bool ProcessValues()
{
for (int i = 0; i < 15; i++)
{
// Do something
return false;
}
return true;
}
我一般喜欢做这种过度引入额外的本地变量来跟踪“有我完成了” - 虽然这会努力的,当然。
有多糟糕goto语句真的,为什么?
它是给所有正常的原因非常糟糕。 在不支持它们的语言模仿标记循环时,这是prefectly罚款。
与真正应该被理解为同一单位在许多情况下,分散的逻辑功能将取代它。 这使得它难以阅读。 没有人喜欢遵循的功能没有做任何事情,直到在旅途的终点,当你已经有点忘记你来自哪里开始痕迹。
与布尔和一堆额外的IFS和休息更换它是真的很笨重,使其难以按照真实意图,像任何噪音。
在java的 (和JavaScript),这是完全可以接受的(标记为循环):
outer: while( true ) {
for( int i = 0; i < 15; ++i ) {
break outer;
}
}
在C#中,它看起来像很接近相当于是不是:
while( true ) {
for (int I = 0; I < 15; I++) {
goto outer;
}
}
outer:;
因为这个词的goto
,这使得人们放弃他们所有的常识,使他们的上下文链接XKCD不管一种心理作用。
有没有打破主循环比使用“转到”语句更有效的方式?
在某些情况下没有,这就是为什么其他语言提供标记环和C#提供了goto
。 请注意,您的例子过于简单,这使得因为他们量身定做的示例中的变通看起来还不错。 其实,我也可以同样建议如下:
for (int I = 0; I < 15; I++) {
break;
}
这个怎么样:
int len = 256;
int val = 65536;
for (int i = 0; i < len; i++)
{
for (int j = 0; j < len; j++)
{
if (i + j >= 2 * val)
{
goto outer;
}
val = val / 2;
}
}
outer:;
这是否仍然看起来好给你:
int len = 256;
int val = 65536;
for (int i = 0; i < len; i++)
{
if (!Inner(i, ref val, len))
{
break;
}
}
private bool Inner(int i, ref int val, int len)
{
for (int j = 0; j < len; j++)
{
if (i + j >= 2 * val)
{
return false;
}
val = val / 2;
}
return true;
}
我将与所有在这里的其他答案的强烈反对。 你目前使用的代码goto
有什么不妥的地方。 还有一个原因是C#有一个goto
语句,恰恰是这些类型的场景,你形容。
goto
压根儿就因为在20世纪70年代及以前人们一负的耻辱,其中控制流程跃升遍布因为地方会写可怕的,完全不可维护的代码goto
。 C#的goto
甚至不允许方法之间的转换! 然而,仍然有反对这种不合理的歧视。
在我看来,是绝对没有错用“现代” goto
跳出内部循环。 该“方案”的人提供最终总是被更加复杂和难以阅读 。
方法一般都应该是可重复使用的 。 使整个单独的方法为一个循环,这将永远只能得到从一个位置叫的内部,并且其中方法实现最终可能是在源代码中的一些较远的地方,是不是在改善。
这种愚蠢的运动,以避免goto
基本上是政治正确的,但在编程世界的等价物。
我同意有关如何坏转到大部分答案。
我sugestion避免GOTO是做这样的事情:
while (condition) { // Main Loop
for (int i = 0; i < 15; i++) { // Secondary loop
// Do Something
if(someOtherCondition){
condition = false // stops the main loop
break; // breaks inner loop
}
}
}
我有时用“GOTO”,我发现它看起来不错,像上面的例子;
bool AskRetry(Exception ex)
{
return MessageBox.Show(you know here...) == DialogResult.Retry;
}
void SomeFuncOrEventInGui()
{
re:try{ SomeThing(); }
catch (Exception ex)
{
if (AskRetry(ex)) goto re;
else Mange(ex); // or throw or log.., whatever...
}
}
我知道你可以做同样的事情递归,但谁在乎它只是工作,我使用。
我的一位同事(谁在固件程序拥有15年以上),我使用goto所有的时间。 然而,我们只用它来处理异常! 例如:
if (setsockopt(sd,...)<0){
goto setsockopt_failed;
}
...
setsockopt_failed:
close(sd);
据我所知,这是C.处理异常的最好方式,我相信,我支持C#了。 另外,我不是唯一一个谁是这样认为的: 在C或C好goto方法的例子++
我个人喜欢把goto语句为“goto语句导致地狱” ......在许多方面,这是真实的,因为它可以导致高度不可维护的代码和非常糟糕的做法。
话虽这么说,它仍然是实现的一个原因,而使用时,应该尽量少用,如果没有其他解决方案可用。 面向对象的语言借给自己并不是真正需要它(很多)。
唯一的时候,我曾经看到它使用了这些天是混淆...使用goto语句创建一个从地狱代码,所以人们将试图理解它而却步的GOOT例子!
有些语言取决于相当于关键字。 例如,在x86的装配台你的关键字,如JMP(跳转),JE(跳转如果相等)和JZ(跳转如果为零)。 这些经常需要使用汇编语言,因为在这个级别没有OO,还有一些其他的方法在应用程序中走动。
据我所知......呆在远离它,除非绝对必要的。