• 离开函数的时机


    离开函数的三种方式中,抛出异常的时机是无法选择的,它关系到函数能否正常执行或者是严重的安全问题,因此一旦出现问题,必须立即抛出异常。而函数自然退出也没有什么值得讨论的意义。真正能影响代码逻辑的,则是通过return语句进行的强制返回。根据结构化程序设计的要求,函数应该分别只有一个入口和出口——这无疑是否定了在函数结尾处之外的位置使用return的权利。不过在实际开发过程中,单出口的要求并不那么实用。例如下面这个程序:

    代码示例7-15:使用多出口模式的典型示例
    public static PhotoFormat FromExtension(string extension)
    {
        switch (extension.ToLower())
        {
            case ".bmp":
                return PhotoFormat.Bmp;
            case ".gif":
                return PhotoFormat.Gif;
            case ".jpg":
            case ".jpeg":
                return PhotoFormat.Jpeg;
            case ".png":
                return PhotoFormat.Png;
            case ".tif":
            case ".tiff":
                return PhotoFormat.Tiff;
            default:
                return PhotoFormat.Unknown;
        }
    }

    这个程序完全违背了单出口的设计原则,但它仍然非常直观,逻辑清晰可见。阅读程序时,一眼可以看出这个并列关系,一个分支读完,就知道程序执行完毕,无须再阅读后面的部分。相反,如果将其改为单出口模式,我们还必须再引入一个临时的本地变量:

    public static PhotoFormat FromExtension(string extension)
    {
        PhotoFormat result = null;
        switch (extension.ToLower())
        {
            case ".bmp":
                result = PhotoFormat.Bmp;
                break;
            case ".gif":
                result = PhotoFormat.Gif;
                break;
            case ".jpg":
            case ".jpeg":
                result = PhotoFormat.Jpeg;
                break;
            case ".png":
                result = PhotoFormat.Png;
                break;
            case ".tif":
            case ".tiff":
                result = PhotoFormat.Tiff;
                break;
            default:
                result = PhotoFormat.Unknown;
                break;
        }
        return result;
    }

    这不但增添了许多break语句,读者读完case分支之后,不得不再寻找switch之后的语句继续阅读,因为他们并不知道后面还会发生什么。代码的可读性显然不如前者。不过,如果分支本身并不能解决所有问题的话,或者并不是每个分支都可以独立完成任务时,下面的单出口模式则更为严谨:
       1:  //代码示例7 16: 采用单出口模式的典型示例
       2:  public Question AddNew(string typeCode)
       3:  {
       4:      Question newq = null;
       5:   
       6:      switch (typeCode)
       7:      {
       8:          case QuestionTypes.Text:
       9:              newq = new TextQuestion(ownerQuestionnaire);
      10:              break;
      11:   
      12:          case QuestionTypes.RadioChoices:
      13:              newq = new RadioChoicesQuestion(ownerQuestionnaire);
      14:              break;
      15:              
      16:          case QuestionTypes.CheckChoices:
      17:              newq = new CheckChoicesQuestion(ownerQuestionnaire);
      18:              break;
      19:   
      20:          case QuestionTypes.RadioTableChoices:
      21:              newq = new RadioTableChoicesQuestion(ownerQuestionnaire);
      22:              break;
      23:   
      24:          default:
      25:              throw new InvalidCastException("未知的问题类型标识:" + typeCode);
      26:      }
      27:   
      28:      Add(newq);
      29:      return newq;
      30:  }

    由于switch中每个分支并不能完成所有任务,它们在给出一个中间结果后,还需要进一步的处理。在这个程序中,处理只是简单地调用Add函数,似乎直接写进case分支也不会增加太多的复杂度。但如果这个处理涉及到更多的操作时,分散在case分支内就会导致代码冗余。应该让switch结构专心产生一个中间结果,然后再让后面的代码继续工作,最后从一个出口离开函数。

  • 相关阅读:
    Javascript动画模拟
    C#导出Excel
    Google Maps API
    动态管理视图和函数
    HttpWebRequest和HttpWebResponse实例
    从零开始学Java 第19章 网络编程
    从零开始学Java 第15章 Java输入输出流
    从零开始学Java 第21章 集合框架
    从零开始学Java 第13章 多线程
    从零开始学Java 第14章 Applet程序
  • 原文地址:https://www.cnblogs.com/starlet/p/2417871.html
Copyright © 2020-2023  润新知