打破包含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;} });