C# 中断包含switch语句的while循环

C# 中断包含switch语句的while循环,c#,while-loop,break,C#,While Loop,Break,我很难弄清楚如何打破包含switch语句的循环。断开开关,而不是环路 也许有一个更优雅的解决方案。我已经实现了一个标志,它以true开始,设置为false并结束循环。你能提供更好的解决方案吗 背景:此代码用于条形码工作流系统。我们有内置条形码扫描仪的袖珍电脑。此代码用于其中一个函数中。它在整个例程中提示用户输入不同的数据段。这一部分允许他们滚动一些库存记录,在PocketPC终端上显示这些信息(分页结果),并允许他们输入“D”表示完成,输入“Q”表示退出 以下是当前需要改进的C#示例: do {

我很难弄清楚如何打破包含switch语句的循环。断开开关,而不是环路

也许有一个更优雅的解决方案。我已经实现了一个标志,它以true开始,设置为false并结束循环。你能提供更好的解决方案吗

背景:此代码用于条形码工作流系统。我们有内置条形码扫描仪的袖珍电脑。此代码用于其中一个函数中。它在整个例程中提示用户输入不同的数据段。这一部分允许他们滚动一些库存记录,在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

谢谢,

对于多级中断,您必须使用goto语句。这似乎是C#中唯一的“干净”方式。使用标志也很有用,但如果循环运行时遇到其他困难,则需要额外的代码


值得注意的是,其他一些非c语言通过执行
中断级别来实现多级中断(Java同样无用,因为它使用了伪装成continue的goto.:P)

标志是实现这一点的标准方法。我知道的唯一其他方法是使用

goto

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


然而,如果你选择这样做,拿着干草叉的愤怒暴徒会成为职业危害。

我所知道的唯一的另一种方式是可怕的后路


然而,我看不出你为什么要在这种情况下使用它。您实现的方式运行良好,并且比goto更易于维护。我会保留你所拥有的。

在我看来,这似乎是打破
循环的完美方式。它做你所期望的,没有副作用。我可以考虑做些什么

if(!keepOnLooping)
  break;

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

这里的一个选项是将这个循环重构成一个方法(“提取方法”),并使用
返回

将其包装到函数中并使用return语句退出。怎么样?

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

为什么不将开关包装到一个返回布尔值的方法中以继续循环?这样做的副作用是使代码更具可读性。有人写论文说我们根本不需要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)

我发现这张表格更具可读性:

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; 
    } 
}

你不能轻易地跳出外循环,但你可以继续

如果你颠倒你的逻辑,你就会得到这个。 注意,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");
写一些类似于:

case "Exit/Break" :
                  //Task to do
                    if(true)
                      break;
此中断不会与任何情况关联。它将属于
while
循环。

另一个(不太好)选择是唯一地处理
情况
,在这种情况下,您必须立即使用
if
来“打破循环”,并将其移出
开关
块。如果开关箱很长,则不太美观:

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
您还可以将
案例
本身作为
条件的一部分,而
循环考虑到您只需中断循环,表达式本身的计算非常简单(如读取变量)



另外,如果由于某种原因无法将整个过程重构为新方法(这是最优雅的解决方案),那么您也可以依靠匿名委托在现有方法中执行相同的操作。

可能有效,也可能无效,但lamda为什么不尝试一下呢

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

在我看来,这很好,标志变量是检查循环条件的标准方法。在Java(和其他一些语言)中,标记循环并使用a将是最简单的答案。虽然
goto
可能令人害怕,在少数情况下,它实际上是有用的,我相信这就是其中之一。虽然这对大多数应用程序都很好,但是
switch
if/else
之间有一个重要的区别,编译器通常可以通过使用跳转表来优化“分支”操作,导致更快的代码。Steve,这里的代码正在等待用户输入。它已经在那里呆了数十亿纳秒,什么也没做。不管是用一纳秒还是一百纳秒来计算出输入的字符是什么,这似乎完全无关。优化应该由关于真实世界用户关注点的经验数据驱动,而不是由对编译器可能做什么的纸上谈兵的猜测驱动。我同意Steve的观点,但在某些简单的情况下,将逻辑更改为if/else会起作用。切换到for/foreach?你的意思是别的。为什么不
if/else
。实际上,我从来不会以这种方式使用ToUpper()进行不区分大小写的比较。15年的经验告诉我,有时goto是最好的、快速的和优化的选择,将算法放在一个小地方:保持它的快速、高效、原子性,而不破坏它的一千个部分,减少不必要的调用。例如,声波分析、机器视觉、实时等。一个标志不会使它变慢,我认为这是不可能的,但许多标志可能是一个阅读问题。
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");
while(  (expr) => (){
switch(expr){
case 1: dosomething; return true; 
case 2 : something;return true;
case exitloop:return false;}
});