Language agnostic 为什么使用开关状态而不是if-else状态?

Language agnostic 为什么使用开关状态而不是if-else状态?,language-agnostic,switch-statement,Language Agnostic,Switch Statement,开关似乎毫无用处,因为它们可以被if-else语句替换,而if-else语句的作用远不止是匹配char/int/enum等。我只能想到开关的一个很好的用途,那就是解释命令行参数 switch语句的一些实际用途是什么?当我使用枚举来指定我的方法应该采取的操作时,我使用switch。当操作相互排斥时,它会有所帮助。有很多情况,我们必须处理的一个问题是,如果有很多选项,语法会稍微压缩一些,有时比if/then语法更容易阅读 尽管有一个论据可以支持任何一种方式,但我发现在有多个选项的情况下,开关更易于阅

开关似乎毫无用处,因为它们可以被if-else语句替换,而if-else语句的作用远不止是匹配char/int/enum等。我只能想到开关的一个很好的用途,那就是解释命令行参数


switch语句的一些实际用途是什么?

当我使用枚举来指定我的方法应该采取的操作时,我使用switch。当操作相互排斥时,它会有所帮助。

有很多情况,我们必须处理的一个问题是,如果有很多选项,语法会稍微压缩一些,有时比if/then语法更容易阅读


尽管有一个论据可以支持任何一种方式,但我发现在有多个选项的情况下,开关更易于阅读、维护和理解。我还将其用于工厂模式类型的情况,这有助于记录。

这是使用该语言的正确方法。它允许编译器进行一些优化,并使代码更容易被不是您的人阅读


此外,在某些语言中,您可以切换枚举,如果您丢失了值,编译器将发出警告(我认为)。

您可以从switch语句中删除中断。这样你就可以做到:

案例A:

基本B


这样你就可以让case_a合并它下面的所有其他case,直到它遇到一个中断。用“如果”来做这件事可没那么好

您需要记住,交换机更容易维护——一大堆嵌套的ifs和ELSE很快就会成为维护的难题


开关允许更容易地插入新案例。

开关在许多语言中针对特定上下文进行了优化。通常在可能的情况下,它们会创建一个跳转表甚至哈希表。实际上,当可以使用开关时,它很可能会比使用if/else的(逻辑上)相同代码执行得更好。

它有助于可读性-一目了然,我知道应该为哪个代码块运行的决定是基于同一变量的不同值。

在一些情况下,switch更具可读性,而且很方便。通常,当您有一组选项时

以下是其中之一:

    int numDays = 0;
    int month = 2;
    int year = 2010;

    // find the number of days in the month
    switch (month) {
        case 1:
        case 3:
        case 5:
        case 7:
        case 8:
        case 10:
        case 12:
            numDays = 31;
            break;
        case 4:
        case 6:
        case 9:
        case 11:
            numDays = 30;
            break;
        case 2:
            if ( ((year % 4 == 0) && !(year % 100 == 0))
                 || (year % 400 == 0) )
                numDays = 29;
            else
                numDays = 28;
            break;
        default:
            System.out.println("Invalid month.");
            break;
    }

在我看来,使用开关vs if/else有两个原因:

  • 编译器可能能够更好地优化开关
  • switch语句更清楚地表达了代码的逻辑。具体来说,就是根据某事物的价值而不是更复杂的逻辑来选择不同的分支。到目前为止,这是对我来说更重要的原因

如果我比较同一变量的多个值,我总是使用开关-开关比长的if-elseif链编码更快(更容易维护)。想象一下更改变量名,使用一个开关,它将是一次编辑,使用if-elseif链,它将是多个

此外,根据选择的语言,您可以使用case fall-through“feature”,其中与if-elseif链一样,您最终会得到重复的代码。

编译器将switch语句转换为分派表可能比将等效的if/else soup转换为分派表更容易。如果(且仅当)这是真的,那么您应该将O(1)分派到相关代码,而不是O(logn)(或者,如果If/else代码写得不好,则为O(n))

在某些(尽管不是所有)情况下,使用switch检查是否涵盖了必要的测试可能比使用if/else更容易。

几点:

  • 某些语言允许您切换其他值类型,例如字符串(Coldfusion就是一个很好的例子)
  • switch语句可能比一大块if/elseif/else语句更容易阅读
  • 在switch语句中,您可以在案例结束时中断,或者允许代码继续处理语句中的其他案例。此功能允许您轻松地对if/elseif/else语句不允许您轻松执行的某些规则建模
  • 正如其他人提到的,请记住编译器和引擎都有优化器,switch语句的优化方式也不同

  • 。它在现代的有用性是有争议的,但它的惊人性却并非如此。

    对于Perl,使用可以显著降低代码的复杂性

    比较一下这两个例子

    • 使用:

    • 使用替换新操作员

      my $num_days;
      for( 1,3,5,7,8,10,12 ){
        if( $month == $_ ){
          $num_days = 31;
          last;
        }
      }
      for( 4,6,9,11 ){
        if( $month == $_ ){
          $num_days = 30;
          last;
        }
      }
      if( $month == 2 ){
        $num_days = 29;
        $num_days = 28 if     $year % 4;
        $num_days = 28 unless $year % 100;
        $num_days = 29 unless $year % 400;
      }
      unless( defined $num_days ){
        print "Invalid month.\n"
      }
      

    在大多数情况下,我更喜欢使用映射到交换机

    if (actionMap.contains(choice)) {
      Action a = actionMap.get(choice);
      a.execute();
    } else {
      //do something else
    }
    
    但是,如果选择过于复杂,无法转化为地图,或者可能需要采取多项行动,则最好进行切换

    switch (choice) {
      case 1: actionOne(); break;
      case 2: if(actionOne()) {actionTwo()}; break; 
      case 3: if(!actionOne() && (actionTwo() > 1)) {actionThree()}; result = 7;break; 
      default: result = actionTwo();
    }
    

    遗憾的是,有时需求是复杂的。Switch在嵌套if/else构造的简化版本的情况下非常有用。

    Switch语句非常适合编写有限状态机,

    在我看来,Switch的主要优点是它使读者立即明白所有选项都依赖于同一个变量。当然,您可以编写一个if/elseif/elseif块来完成相同的任务,但是读者必须仔细检查每次测试的变量是否相同

    还有一个噩梦般的维护场景,在同一个变量上有一个很长的if/elseif,有人决定更改变量名,所以他更改了所有的if。。。但他错过了一个


    正如其他人所指出的,还有一个事实,编译器通常可以更好地优化它。

    不要问python程序员这个问题,因为该语言没有switch语句,而是鼓励使用字典

    为了回答你的问题,我可以想出一个switch语句很有用的例子。 当语言/编译器/静态分析器可以确保您检查了所有情况时,它非常有用。这很有效
    switch (choice) {
      case 1: actionOne(); break;
      case 2: if(actionOne()) {actionTwo()}; break; 
      case 3: if(!actionOne() && (actionTwo() > 1)) {actionThree()}; result = 7;break; 
      default: result = actionTwo();
    }