解决过度使用break语句的方法

本文关键字:语句 方法 break 解决 | 更新日期: 2023-09-27 17:51:21

我有一个功能完备的程序,现在我正在重构它。我只是在学习c#的过程中,所以最初的代码是相当可怕的,尽管它运行得很好。该程序的要求之一是用户能够在任何时候返回到主菜单。我是这样做的:

static bool bouncer = false
static void Exit(string input)
{
    if (input == "'t")
    {
        bouncer = true
    }
}
static string Prompt(string msg)
{
    // takes input and passes it to Exit() then returns the input
}
static string FunctionA()
{
    while(true)
    {
        if (bouncer == true)
        {
            break;
        }
        Prompt("whatever")
        if (bouncer == true)
        {
            break;
        }
        Prompt("whatever")
        if (bouncer == true)
        {
            break;
        }
        // return some stuff
    }
}
static void Main()
{
    bouncer = false
    // writes the menu to console and handles UI
    // FunctionA
{

如果用户在任意输入点输入"tab"字符,则变量bouncer被设置为true。break语句条件的激增提供了实际返回到Main()的结构。这显然不是一个很好的解决方案,它使代码难以阅读。

我认为完成相同任务的其他尝试有:

  1. 直接跳转回Main()的Goto语句。我放弃了这个,因为goto在c#中的作用范围非常有限,我认为没有任何好的方法可以使它在这种情况下工作。

  2. 直接从Exit()调用Main()。这可能是一个坏主意,我不能这样做,因为显然Main()在某种程度上是"受保护的"。

  3. 使用事件对按下TAB或ESC做出反应。我不清楚如何使用事件来做到这一点,因为我仍然无法从事件中跳出来。我的理解是,break语句实际上必须包含在需要中断的循环中,而不是写入从循环内调用的不同函数中。

任何建议都非常感谢。我希望有一些事情要做的事件处理,或者我忽略了一些更简单的东西。谢谢!

解决过度使用break语句的方法

作为编码风格的问题,它的工作方式,但被认为是丑陋的。不幸的是,如果你需要在工作之间立即休息一下,没有很多方法可以解决这个问题。

你可以改变你当前使用break的格式为使用"if( bContinue ) { /* do next section of work */ }"控件样式。它将跳出while循环的代码更改为:

static string FunctionA()
{
    bool bContinue = true;
    while( true == bContinue )
    {
        // Do initital work.
        //
        // Initial work can set bContinue to false if any error condition
        // occurs.
        if( true == bContinue ) 
        {
            // Do more work.
            int returnCheck = MakeACall(); // Presume MakeACall returns negative interger values for error, 0 or positive values for success or success with condition/extra information.
            if( 0 < returnCheck )
            {
                bContinue = false;
            }
        }
        if( true == bContinue ) 
        {
            Prompt("whatever")
            // Do more work.
            bContinue = MakeASecondCall(); // Presume that MakeASecondCall returns true for success, false for error/failure
        }
        if( true == bContinue ) 
        {
            Prompt("whatever")
            // Do more work.
            // If error encountered, set bContinue to false.
        }
        if( true == bContinue ) 
        {
            Prompt("whatever else")
            // Do more work.
            // If error encountered, set bContinue to false.
        }
        // Done with loop, so drop out.
        bContinue = false;
        // return some stuff
    }
}

看看你的伪代码,它读起来就像你只在你的工作循环中做了一次传递。如果是这样,您可以切换到Do-While(false)格式,并使用中断只是下降到底部。或者,如果你只做一次通过你的FunctionA,只要去掉WhileDo-While控制结构,只使用if(true==bContinue){ /* Do more work */ }。它不是最干净的代码,但是当您执行长时间的串行工作时,如果您不打算使用whiledo-while来控制流,您最终会得到这样的结构。

使用if(bContinue){}风格的缺点是,当错误条件发生在过程的早期阶段时,如果错误发生在工作的顶部附近,那么代码不会像break一样快速地从while()do-while()结构中退出,因为代码将测试一系列if语句,然后跳过它们。但它是可读的,如果你使用一个描述性的名称为你的控制变量(即,nContinuebContinueworkLoopControl),它应该是相当明显的,它是主控制标志的功能的工作流程,无论谁工作或审查你之后的代码。

不要使用无限循环和break语句,而是尝试使用条件标志。

static void FunctionA()
{
  bool done = false;
  string response = string.Empty;
  while (!done)
  {
    response = Prompt("whatever");
    if(response == ''t')
    {
      done = true;
    }
  }
}

作为旁注,我不知道为什么你有'string'作为几个方法的返回类型(例如,'FunctionA'),当你不使用返回值。这就是为什么我上面给出的代码是'void'