我无法弄清楚如何突破包含switch语句的循环。中断突破开关,而不是循环。
这可能是一个更优雅的解决方案。我已经实现了一个标志,该标志以true开头并设置为false并结束循环。你能提供更好的解决方案吗?
背景:此代码用于条形码工作流程系统。我们有内置条形码扫描仪的PocketPC。此代码用于其中一个功能。它会在整个例程中提示用户输入不同的数据。这件作品允许他们滚动显示在PocketPC终端上显示该信息的一些库存记录(分页结果),并允许他们输入“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
谢谢,
答案 0 :(得分:43)
答案 1 :(得分:38)
我发现这种形式更具可读性:
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;
}
}
答案 2 :(得分:29)
此处的一个选项是将此循环重构为方法(“提取方法”),并使用return
。
答案 3 :(得分:12)
我所知道的另一种方式是可怕的goto。 MSDN also says this.
但是,我认为没有理由在这种情况下使用它。您实现的方式工作正常,并且比goto更易于维护。我会保留你拥有的东西。
答案 4 :(得分:10)
您必须使用goto语句进行多级中断。它似乎是C#中唯一“干净”的方式。使用标志也很有用,但如果循环有其他运行困境,则需要额外的代码。
http://msdn.microsoft.com/en-us/library/aa664756(VS.71).aspx
可能有趣的是,通过执行break levels;
,其他一些非c语言有多级别中断(但Java也没用,因为它使用goto伪装成一个继续......:P)
答案 5 :(得分:8)
为什么不将开关包装成一个返回布尔值以保持循环的方法?这样可以使代码更具可读性。有人写论文说我们毕竟不需要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;
}
答案 6 :(得分:4)
标志是执行此操作的标准方法。我所知道的另一种方法是使用goto
。
答案 7 :(得分:4)
你不能轻易地突破外圈,但你可以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");
答案 8 :(得分:2)
您可以使用switch
语句替换if/else
语句。不需要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)
答案 9 :(得分:1)
IMO,这似乎是打破while
循环的完美方式。它做你期望的没有副作用。我想到了
if(!keepOnLooping)
break;
但这在执行方面并没有什么不同。
答案 10 :(得分:1)
将其包装到函数中并使用return语句退出。怎么样?
答案 11 :(得分:1)
写下类似的内容:
case "Exit/Break" :
//Task to do
if(true)
break;
此中断不会与任何情况相关联。它将属于while
循环。
答案 12 :(得分:0)
您可以将switch语句更改为for / foreach循环。满足条件后,将“keepOnLooping”设置为false,然后使用break退出循环。其余的应该照顾好自己。
答案 13 :(得分:0)
另一个(不那么好)替代方案是唯一地处理case
,你必须立即用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
循环条件的一部分,考虑到你只需要摆脱循环并且表达式本身的计算是微不足道的(比如读取变量)
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");
另外,如果将整个事物重构为一个新方法(这是最优雅的解决方案)由于某种原因是不可接受的,那么你也可以依靠匿名委托在现有方法中做同样的事情。
答案 14 :(得分:-1)
可能或可能不行,但lamda为什么不为了好玩而试一试呢
while( (expr) => (){
switch(expr){
case 1: dosomething; return true;
case 2 : something;return true;
case exitloop:return false;}
});