打破包含switch语句的while循环

我无法弄清楚如何摆脱包含switch语句的循环。 rest突破了开关,而不是循环。

这可能是一个更优雅的解决scheme。 我已经实现了一个标志,开始为真,并设置为false,并结束循环。 你能提供更好的解决scheme吗?

背景:此代码用于条形码工作stream程系统中。 我们有内置有条码扫描器的PocketPC。这些代码被用于其中一个function。 它会在整个例程中提示用户input不同的数据。 这件作品允许他们滚动显示PocketPCterminal上的一些存货logging(分页结果),并允许他们input“D”完成,“Q”退出。

这里是当前的C#示例需要改进:

do { switch (MLTWatcherTCPIP.Get().ToUpper()) { case "": //scroll/display next inventory location MLTWatcherTCPIP.TerminalPrompt.ScrollBodyTextDown(); break; case "P": //scroll/display previous inventory location MLTWatcherTCPIP.TerminalPrompt.ScrollBodyTextDown(); break; case "D": //DONE (exit out of this Do Loop) // break; // this breaks out of the switch, not the loop // return; // this exists entire method; not what I'm after keepOnLooping = false; break; case "Q": //QUIT (exit out to main menu) return; default: break; } } while (keepOnLooping); 

这里是VB.NET中的代码示例

 Do Select Case MLTWatcherTCPIP.Get().ToUpper Case "" ''#scroll/display next inventory location MLTWatcherTCPIP.TerminalPrompt.ScrollBodyTextDown() Case "P" ''#scroll/display previous inventory location MLTWatcherTCPIP.TerminalPrompt.ScrollBodyTextUp() Case "D" ''#DONE (exit out of this Do Loop) Exit Do Case "Q" ''#QUIT (exit out to main menu) Return End Select Loop 

谢谢,

我发现这个表单是更加可读的:

 bool done = false; while (!done) { switch (MLTWatcherTCPIP.Get().ToUpper()) { case "": //scroll/display next inventory location MLTWatcherTCPIP.TerminalPrompt.ScrollBodyTextDown(); break; case "P": //scroll/display previous inventory location MLTWatcherTCPIP.TerminalPrompt.ScrollBodyTextDown(); break; case "D": //DONE (exit out of this Do Loop) done = true; break; case "Q": //QUIT (exit out to main menu) return; default: break; } } 

我会尽量避免它,但你可以使用…

但是,如果您select这样做,愤怒的暴徒与干草叉成为职业危害。

这里的一个select是将此循环重构为一个方法(“提取方法”),并使用return

我知道的唯一的另一种方式是可怕的转到。 MSDN也这样说。

不过,我没有看到你在这种情况下使用它的原因。 你实施的方式工作正常,比goto更可维护。 我会保持你的。

您必须使用goto语句来进行多级别rest。 这似乎是在C#中唯一的“干净”的方式。 使用标志也是有用的,但如果循环有其他运行的困境,则需要额外的代码。

http://msdn.microsoft.com/en-us/library/aa664756(VS.71).aspx

注意到一些其他非c语言通过做break levels ;有多个级别的rest可能是有趣的break levels ; (Java是一样的,虽然,因为它使用了一个伪装成一个继续..:P)

为什么不把开关换成一个返回布尔值的方法来保持循环呢? 这会使代码更具可读性。 有人写了一篇文章,说我们毕竟不需要goto语句;)

 do { bool keepOnLooping = TryToKeepLooping(); } while (keepOnLooping); private bool TryToKeepLooping() { switch (MLTWatcherTCPIP.Get().ToUpper()) { case "": //scroll/display next inventory location MLTWatcherTCPIP.TerminalPrompt.ScrollBodyTextDown(); break; case "P": //scroll/display previous inventory location MLTWatcherTCPIP.TerminalPrompt.ScrollBodyTextDown(); break; case "D": //DONE (exit out of this Do Loop) // break; // this breaks out of the switch, not the loop // return; // this exists entire method; not what I'm after return false; case "Q": //QUIT (exit out to main menu) return true; default: break; } return true; } 

标志是执行此操作的标准方法。 我知道的唯一的另一种方式是使用goto

你不能轻易地脱离外部循环,但你可以continue下去。

如果你逆转你的逻辑,那么你得到这个。 请注意,switch语句之后立即出现break以退出循环。

在我看来,这不是很可读的代码,我认为一个标志仍然是最好的。

  do { switch (Console.ReadKey().KeyChar.ToString()) { case "U": Console.WriteLine("Scrolling up"); continue; case "J": Console.WriteLine("Scrolling down"); continue; case "D": //DONE (exit out of this Do Loop) break; case "Q": //QUIT (exit out to main menu) return; default: Console.WriteLine("Continuing"); continue; } break; } while (true); Console.WriteLine("Exited"); 

您可以用一个if/else语句replaceswitch语句。 没有goto需要和break语句离开循环:

 do { String c = MLTWatcherTCPIP.Get().ToUpper(); if (c = "") MLTWatcherTCPIP.TerminalPrompt.ScrollBodyTextDown(); else if (c = "P") MLTWatcherTCPIP.TerminalPrompt.ScrollBodyTextUp(); else if (c = "D") break; else if (c = "Q") return; else { // Handle bad input here. } } while (keepLooping) 

把它包装成一个函数并使用return语句退出。 那个怎么样?

国际海事组织,这似乎是一个完美的方式打破了一个while循环。 它做你所期望的没有副作用。 我可以想到做

 if(!keepOnLooping) break; 

但是这在执行方面并没有什么不同。

写下类似于:

 case "Exit/Break" : //Task to do if(true) break; 

这个突破将不会与任何情况相关联。 它将属于while循环。

您可以将switch语句更改为for / foreach循环。 一旦条件满足,将“keepOnLooping”设置为false,然后使用break来退出循环。 其余的应该照顾自己。

另一个(不是很好)的select是独特地处理你必须马上“跳出循环”的if ,并将其从switch块中移出。 如果开关柜非常长,不是非常优雅:

 do { var expression = MLTWatcherTCPIP.Get().ToUpper(); if (expression = "D") //DONE (exit out of this Do Loop) { statement; break; } switch (expression) { case "": //scroll/display next inventory location MLTWatcherTCPIP.TerminalPrompt.ScrollBodyTextDown(); break; case "P": //scroll/display previous inventory location MLTWatcherTCPIP.TerminalPrompt.ScrollBodyTextDown(); break; case "Q": //QUIT (exit out to main menu) return; default: break; } } while (true); //or whatever your condition is 

你也可以把case本身作为while循环的条件的一部分,考虑到你只需要跳出循环,并且expression式本身的计算是微不足道的(就像读一个variables)。

 do { switch (expression) { case "": //scroll/display next inventory location MLTWatcherTCPIP.TerminalPrompt.ScrollBodyTextDown(); break; case "P": //scroll/display previous inventory location MLTWatcherTCPIP.TerminalPrompt.ScrollBodyTextDown(); break; case "Q": //QUIT (exit out to main menu) return; default: break; } } while (condition && expression != "D"); 

另外,如果将整个事物重构为一个新的方法(这是最优雅的解决scheme)是不可接受的,那么你也可以依靠一个匿名委托来在现有的方法中做同样的事情。

可能或者可能不工作,但拉姆达为什么不尝试只为乐趣

 while( (expr) => (){ switch(expr){ case 1: dosomething; return true; case 2 : something;return true; case exitloop:return false;} });