[英]Break out of a while loop that contains a switch statement
我无法弄清楚如何跳出包含 switch 语句的循环。 Break 是跳出开关,而不是循环。
可能有一个更优雅的解决方案。 我已经实现了一个标志,它开始为真,然后设置为假并结束循环。 你能提供更好的解决方案吗?
背景:此代码用于条码工作流系统。 我们有内置条形码扫描器的 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
谢谢,
我发现这个表格更具可读性:
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;
}
}
这里的一种选择是将此循环重构为一个方法(“提取方法”),并使用return
。
我所知道的唯一其他方法是可怕的 goto。MSDN 也这么说。
但是,我看不出您在这种情况下为什么要使用它。 您实施的方式工作正常,并且比 goto 更易于维护。 我会保留你所拥有的。
您必须使用 goto 语句进行多级中断。 它似乎是 C# 中唯一的“干净”方式。 使用标志也很有用,但如果循环有其他运行困境,则需要额外的代码。
http://msdn.microsoft.com/en-us/library/aa664756(VS.71).aspx
有趣的是,其他一些非 c 语言通过执行break levels ;
具有多级中断break levels ;
(不过,Java 也同样没用,因为它使用伪装成 continue 的 goto.. :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;
}
你不能轻易跳出外循环,但你可以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");
标志是执行此操作的标准方法。 我所知道的唯一另一种方法是使用goto
。
您可以用if/else
语句替换switch
语句。 不需要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)
写一些类似的东西:
case "Exit/Break" :
//Task to do
if(true)
break;
此中断不会与任何情况相关联。 它将属于while
循环。
IMO,这似乎是打破while
循环的完美方式。 它可以满足您的预期而没有副作用。 我可以想到做
if(!keepOnLooping)
break;
但这在执行方面并没有什么不同。
将其包装成一个函数并使用 return 语句退出。 怎么样?
另一个(没有那么大)替代方案是唯一处理的case
,你必须有一个“循环打出来” if
马上和其移出的switch
块。 如果 switch-case 很长,那就不是很优雅了:
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");
此外,如果由于某种原因将整个事物重构为一个新方法(这是对此最优雅的解决方案)是不可接受的,那么您也可以依靠匿名委托在现有方法中执行相同的操作。
您可以将 switch 语句更改为 for/foreach 循环。 一旦满足条件,将“keepOnLooping”设置为 false,然后使用 break 退出循环。 其余的应该照顾好自己。
可能会或可能不会起作用,但是 lamda 为什么不只是为了好玩而试一试
while( (expr) => (){
switch(expr){
case 1: dosomething; return true;
case 2 : something;return true;
case exitloop:return false;}
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.