【问题标题】:How can I get rid of these else if statements and make the code look better?我怎样才能摆脱这些 else if 语句并使代码看起来更好?
【发布时间】:2020-09-27 13:00:27
【问题描述】:

我有这个 c# 代码

progressBar1.Increment(1);
if (progressBar1.Value > 5 && progressBar1.Value < 10)
{
  label1.Text = "Some text...";
  timer1.Stop();
  timer1.Start();
  timer1.Interval = 1000;
}
else if (progressBar1.Value > 10 && progressBar1.Value < 15)
{
  label1.Text = "Some text 2...";
  timer1.Interval = 250;
}
else if (progressBar1.Value > 15 && progressBar1.Value < 30)
{
  label1.Text = "Some text 3...";
}
else if (progressBar1.Value > 30 && progressBar1.Value < progressBar1.Maximum)
{
  label1.Text = "Some text 4...";
  timer1.Interval = 100;
}
else if (progressBar1.Value == progressBar1.Maximum)
{
  timer1.Stop();
  const string message = "Some cool popup message";
  const string caption = "Test";
  MessageBox.Show(message, caption, MessageBoxButtons.OK);
  Close();
}

我确定这段代码很糟糕,我不是真正的程序员,我只是尝试创建一些有趣的应用程序。我怎样才能摆脱这些冗长的 else if 语句并用更好的东西替换它?我一直在寻找答案和提示,但没有一个对我有帮助。

【问题讨论】:

  • 你可以做一个switch语句。但存在逻辑错误。如果 progressBar1.Value == 10 会发生什么?
  • 最简单的方法是删除条件中的一项。 if
  • 您是否注意到 if 值将是 5.10.15 或 30,因为您使用了 而不是 >= 或
  • 当 value == 10 等时实际上什么都没有发生,它保留以前的 label1.text 并在 value 为 11 时更改它等等。运行程序时我没有遇到任何错误。

标签: c# .net visual-studio performance if-statement


【解决方案1】:

我能想到的两种方法:

使用continue 简化条件并更改流程我在这里假设您处于forwhile 循环中

progressBar1.Increment(1);
if (progressBar1.Value < 5) continue;
if (progressBar1.Value < 10)
{
  label1.Text = "Some text...";
  timer1.Stop();
  timer1.Start();
  timer1.Interval = 1000;
  continue;
}
if (progressBar1.Value < 15)
{
  label1.Text = "Some text 2...";
  timer1.Interval = 250;
  continue;
}
if (progressBar1.Value < 30)
{
  label1.Text = "Some text 3...";
  continue;
}
if (progressBar1.Value < progressBar1.Maximum)
{
  label1.Text = "Some text 4...";
  timer1.Interval = 100;
  continue;
}

  timer1.Stop();
  const string message = "Some cool popup message";
  const string caption = "Test";
  MessageBox.Show(message, caption, MessageBoxButtons.OK);
  Close();

如果不在循环中,则删除 continue 并重新添加 else 语句和最大条件 if。代码只会输入其中一种 if/else 情况。

为了进一步研究,您可以提取到一个函数,但我需要您的整个示例来重构它。

即使进一步研究也可以引导您找到适合您的情况的状态模式,但这有点矫枉过正。

【讨论】:

    【解决方案2】:

    在 C#9(当前为 only available in preview)中,您将能够像这样使用 relational pattern matching

    progressBar1.Increment(1);
    
    switch (progressBar1.Value)
    {
        case > 5 and < 10:
            label1.Text = "Some text...";
            timer1.Stop();
            timer1.Start();
            timer1.Interval = 1000;
            break;
            
        case > 10 and < 15:
            label1.Text     = "Some text 2...";
            timer1.Interval = 250;
            break;
            
        case > 15 and < 30:
            label1.Text = "Some text 3...";
            break;
            
        case > 30 and < progressBar1.Maximum:
            label1.Text     = "Some text 4...";
            timer1.Interval = 100;
            break;
            
        case progressBar1.Maximum:
            timer1.Stop();
            const string message = "Some cool popup message";
            const string caption = "Test";
            MessageBox.Show(message, caption, MessageBoxButtons.OK);
            Close();
            break;
    }
    

    这使得如何细分范围更加清晰。 (据我所知,C# 9 应该会在今年 11 月左右发布。)

    【讨论】:

      【解决方案3】:

      您的代码还不错(除了使用&lt; 而不是&lt;=工作它;'完全可以接受。

      不要误以为代码越少越好。查看一些建议的“改进”。他们做什么很明显,还是您必须花时间思考实际逻辑是什么。我已经看到太多嵌套的三元表达式,这些表达式是由试图破译大脑造成的(更不用说尝试调试表达式的一部分了),而嵌套的 if 会做完全相同的事情并且更容易理解,调试和维护。

      您有 5 种潜在状态,它们之间几乎没有重叠(效果方面)。我会说这是完全可以接受的使用 5 个if 语句。如果它们都是“相等”的情况而不是范围,并且每个都只是设置相同的变量,那么也许像 Dictionary 这样更高级的东西可能会有用,但这里的情况并非如此。

      【讨论】:

        【解决方案4】:

        由于您是初学者,而且我要展示的内容有点复杂,我强烈建议您查看the ternary conditionnal operator,因为这就是我要在这里展示的内容。

        这是一段代码:

                Console.WriteLine(text);
                text = (!(value > 10 && value < 15)) ? "Some text..." : "";
        
                Console.WriteLine(text);
                text = (!(value > 15 && value < 30)) ? "Some text 2..." : "";
        
                Console.WriteLine(text);
                text = (!(value > 30 && value < maximum)) ? "Some text 3..." : "";
        
                Console.WriteLine(text);
                text = (!(value == maximum)) ? "Some text 4..." : "";
        
                Console.WriteLine(text);
                text = "Some cool message";
        
                Console.WriteLine(text);
        

        现在,不要害怕,我会解释的。

        所以这些单行是三元条件。它们基本上是常规的 if/else 条件,但作为一行。它们非常好,可以使您的代码更清晰,而且还可以“花哨”地看待它。

        您应该注意,我使用的不是 WinForms 项目,而是控制台项目,以便于测试。

        如您所见,没有第一个条件,即value &gt; 5 &amp;&amp; value &lt; 10。那只是因为我们不需要它。

        到最后你可能也会感到困惑。如您所见,最终消息不是在条件上,而是在value == maximum 条件之后。为什么?好吧,那只是因为它是如何工作的。如果你有一点看不懂我的话,你真的应该看看我上面发的文章。

        无论如何,这就是传说:

        value是ProgressBar的值,所以这里progressBar1.Value

        maximum是ProgressBar的最大值,所以这里progressBar1.Maximum

        【讨论】:

        • 嗯,其他行怎么样,比如 timer1.interval = 100; ?
        • @NeedHelpSometimes 您可以将它们放在每个“text = ....”行之后。
        【解决方案5】:

        现在你只有几个案例,所以我几乎没有什么不同。如果您有很多案例,则表查找可以使其变得容易得多。

        伪代码:

        struct Case {
          int Min, Max; // inclusive
          String txt; // if not empty
          int TimerValue; // set if greater than zero.
          Func ToCall; // null or lampda
        };
        
        Case cases { 
          { 6, 9, "Text1", 1000, { timer1.Stop(); timer1.Start(); } }, 
          { 11, 14, "Text2, 250, {}},
          etc.
        }
        ASSERT(is_sorted(cases)); // so we don't mess up the order.
        
        auto res = BinarySearch(value, cases);
        if (!res) continue;
        Execute(res);
        

        这种情况多的时候可以省点工作。

        【讨论】:

        • 这种方法通常会减少代码大小和冗余,并且更容易维护(更容易看出范围是正确的,因为它们没有被代码分隔)。唯一的缺点可能是抽象使得调试更加不同,如果需要的话:不可能直接有一个特定值的断点。但总的来说可能是最好的解决方案。
        • @Peter-ReinstateMonica 感谢您更好地解释我的意思:)感谢您的支持。
        【解决方案6】:

        这里有一些你可以寻找的例子。

        switch (value)
        {
             case var expression when value < 0:
                 //some code
                 break; 
        
             case var expression when (value >= 0 && value < 5):
                 //some code
                 break;
        
             default:
                 //some code
                 break;
        }
        

        【讨论】:

        • 关于问题中发布的代码,valueexpression 是什么?
        • 参考这个dotnetperls.com/switch,这个链接可以帮助你了解几种情况。
        猜你喜欢
        • 2012-12-26
        • 1970-01-01
        • 2023-04-01
        • 2017-05-25
        • 2021-01-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多