zoukankan      html  css  js  c++  java
  • 浅尝EffectiveCSharp_5

    Item 10:使用可选参数来减小方法重载 Use Optional Parameters to Minimize Method Overloads

    • 这似乎不是什么很难实现或很新颖的特性(C#4.0新增),只要编译器的支持就可以(VB很早就支持了)。估计加入的原因是群众的呼声太高了。
    • C#中在调用点对已命名的参数进行了支持。这意味着正式参数名称现在是你的公共接口的一部分类型。改变一个公共参数的名称可能会破坏调用代码。这意味着你应该避免在许多情况下使用命名参数,,你也应该避免在公共或受保护的方法中,变化的形式参数的名称对。
    • 当然,没有语言设计者增加了一些功能只是为了增加你的麻烦。增加命名参数是有理由的,他们有积极的用途。命名参数和可选参数,可以限制许多API周围的,特别是对微软Office的COM的API。下面这个代码片断创建了一个Word文档,并插入小段文本,使用传统COM方法: 
      var wasted = Type.Missing;
      var wordApp
      = new Microsoft.Office.Interop.Word.Application();
      wordApp.Visible
      = true;
      Documents docs
      = wordApp.Documents;
      Document doc
      = docs.Add(ref wasted,ref wasted, ref wasted, ref wasted);
      Range range
      = doc.Range(0, 0);
      range.InsertAfter(
      "Testing, testing, testing. . .");

      这里我们对Type.Missing对象使用了4次。任何Office互操作的应用程序都可能使用一个更大的数目Type.Missing的应用对象。这种情况下,那些实例会让你的应用程序,软件构建的实际逻辑变得乱七八糟。这也是后来在C#语言中添加可选命名参数的主要推动力。可选参数是指这些Office API可以为Type.Missing将被使用的地方创建默认值,其中,。这简化了连这么小的片断: 

      var wordApp = new Microsoft.Office.Interop.Word.Application();
      wordApp.Visible
      = true;
      Documents docs
      = wordApp.Documents;
      Document doc
      = docs.Add();
      Range range
      = doc.Range(0, 0);
      range.InsertAfter(
      "Testing, testing, testing. . .");

      命名参数的意思是,在任何带有默认参数的API中,你只需要指定这些你打算使用的参数。它比重载简单多了,加入有四个不同的参数,你就需要创建15个Add()方法来达到同样的不同的重载。而且有些office api 有16个参数,因此使用命名参数要简单的多。

      private void SetName(string lastName, string firstName)
      {
      // elided
      }
      使用命名参数:
      SetName(lastName:
      "Wagner", firstName: "Bill");

       标注的参数的名称,确保人们在以后阅读代码不会不知道的参数是否是正确的顺序。开发人员使用命名参数也将使代码易懂。只要你使用包含同一类型,多个参数的方法是,在调用点命名参数将使你的代码更具可读性。

    • 参数的名字是在callsite存储在msil中的,而不是在callingsite。你可以改变参数的名字,而不用担心是否会破坏调用代码。举个例子,假如你改变了setname方法

      public void SetName(string Last, string First)
      SetName(lastName: "Wagner", firstName: "Bill");//改变参数

      你可以编译发布这个程序集,其他调用这个方法的程序集仍然能正常运行。一旦更新,将无法编译通过。

    • Changing the names of parameters will break client code at compile time.

    • In addition, adding parameters (even if they have default values) will break at runtime.

    • Therefore, adding parameters, even if they are optional parameters, is a breaking change at runtime. If they have default values, it’s not a breaking change at compile time.

     Item 11: 了解简短代码的好处 Understand the Attraction of Small Functions

    •  很多时候,我们对c#编译器进行手动的代码优化。但是,我们的这种行为经常会阻止JIT编译器做更有效的优化。因此,优化的工作就交给JIT吧。最普遍的实例就是,你写一个很复杂的方法来减少对方法的调用。
      public string BuildMsg(bool takeFirstPath)
      {
        StringBuilder msg
      = new StringBuilder();
        if (takeFirstPath)
        {
          msg.Append(
      "A problem occurred.");
          msg.Append(
      "\nThis is a problem.");
          msg.Append(
      "imagine much more text");
        }
        else
        {
          msg.Append(
      "This path is not so bad.");
          msg.Append(
      "\nIt is only a minor inconvenience.");
          msg.Append(
      "Add more detailed diagnostics here.");
        }
        return msg.ToString();
      }

       第一次BuildMsg被调用,两条路径都被JITed.但是,我们只需要其中的一条。假如你修改一下:

      public string BuildMsg2(bool takeFirstPath)
      {
        if (takeFirstPath)
        {
          return FirstPath();
        }
        else
        {
          return SecondPath();
        }
      }

      因为body的每个子句都被作为方法的一个因子,因此两个子方法在主方法被调用前就JIT了。虽然这个例子被人为的拆开了,看起来清楚了很多,但是没什么实际的差别。

    •  体积更小,功能简单的方法更加支持JIT编译器执行enregistration。 Enregistration是一个选择局部变量是存储在寄存器还是堆栈上的进程。简单的控制流也影响JIT编译器更好的注册变量。如果一个函数有一个循环,该循环变量将可能被注册。越简单越好。一个小功能是更有可能包含较少的局部变量,使之更容易在JIT编译器优化寄存器的使用。

      // readonly name property:
      public string Name { get; private set; }
      // access:
      string val = Obj.Name;

      该属性访问器体包含的代码需要较少的指令调用函数:节省注册、执行方法代码,存储函数的返回值。甚至会有更多的工作需要。

    • JIT编译器知道你的需求,所以它会自动内联属性访问器。而简短的方法能提高内联的可能性,但是虚方法和try/catch块无法内联。

    • 总之,为了有利于JIT编译,我们要尽可能使用简短的方法,简短的控制流,更少的分支。It’s not just good practice to write clearer code; it’s how you create more efficient code at runtime.

  • 相关阅读:
    SSHkey的申请
    版本控制系统-集中式VS分布式(分享)
    01-OC中数组NSArray的遍历
    第4周小组作业:WordCount优化
    第2周作业1:开设博客
    第2周个人作业:WordCount
    测试课程总结2017
    优秀博客的评比结果及相关说明
    静态代码检查工具简介
    Selenium安装中的一些问题及解决办法-软硕1703班3组整理分享
  • 原文地址:https://www.cnblogs.com/TivonStone/p/1731464.html
Copyright © 2011-2022 走看看