【问题标题】:Are there benefits to quick-exiting a method or constructor?快速退出方法或构造函数有什么好处?
【发布时间】:2012-03-28 15:12:57
【问题描述】:

我认为这部分与短路逻辑有关,但我找不到任何直接回答我问题的问题。可能的相关问题:Benefits of using short-circuit evaluationWhy use short-circuit code?

考虑以下两个代码块,它们都是类的可能构造函数

public MyClass(OtherClass other){
    if (other != null) {
       //do something with other, possibly default values in this object
    }
}

还有这个

public MyClass(OtherClass other){
    if (other == null)  return;

    //do something with other, possibly default values in this object
}

做后者比做前者有什么好处吗?构造函数中没有其他代码,只是使用other 对象来构造这个的代码。

【问题讨论】:

    标签: c# constructor short-circuiting


    【解决方案1】:

    在这种情况下,您应该做对您和您的同事来说最易读的事情。两种方法之间不太可能有任何可察觉的速度差异。

    【讨论】:

    • 这也是我的想法。只是想看看以一种方式与另一种方式相比是否有性能(或任何其他)好处。
    【解决方案2】:

    唯一的区别是可读性。通过所谓的“快速退出”,您可以停止思考自己所处的条件,因为您不再处于其中。

    【讨论】:

      【解决方案3】:

      后者通常更容易阅读,如果您有多种情况需要终止,那么它会变得更容易。然而,速度没有差异。

      假设你有一个函数接收Int32?,如果值是nulleven或大于100,它就会退出。

      你可以的

      void fn( Int32? num ) {
          if ( num != null ) {
              if ( num < 100 ) {
                  if ( num % 2 != 1 ) { 
                      //method code
      

      或类似的东西

      void fn( Int32? num ) {
          if ( num == null )
              return;
      
          if ( num > 100 )
              return;
      
          if (!(num % 2 != 1)) 
              return;
      
          //method code
      

      现在这个例子有点傻,我现在可以听到你了,为什么不把它们和||&amp;&amp; 放在一起,在这种情况下是的。但是想象一下,如果数据验证比这复杂得多?你最终会得到过度缩进,更难阅读的代码。

      【讨论】:

        【解决方案4】:

        特别针对这种情况,(假设您是人类)需要通读其余的源代码才能到达方法的末尾,而处理器则不需要。第一个示例中的块 if 语句评估条件,如果评估结果为 false,则执行将跳转到方法的末尾。

        【讨论】:

          【解决方案5】:

          我试过这个构造函数

          public AnotherExpense(string param)
              {
                  if (param != null)
                  {
                      Console.WriteLine("test");
                  }
              }
          

          IL 代码

          .method public hidebysig specialname rtspecialname 
              instance void  .ctor(string param) cil managed
          {
            // Code size       20 (0x14)
            .maxstack  8
            IL_0000:  ldarg.0
            IL_0001:  call       instance void AccountParserCSV.Expense::.ctor()
            IL_0006:  ldarg.1
            IL_0007:  brfalse.s  IL_0013
            IL_0009:  ldstr      "test"
            IL_000e:  call       void [mscorlib]System.Console::WriteLine(string)
            IL_0013:  ret
          } // 
          

          如果你把它改成

          public AnotherExpense(string param)
              {
                  if (param == null)
                      return;
          
                      Console.WriteLine("test");
              }
          

          你得到

          .method public hidebysig specialname rtspecialname 
              instance void  .ctor(string param) cil managed
          {
            // Code size       21 (0x15)
            .maxstack  8
            IL_0000:  ldarg.0
            IL_0001:  call       instance void AccountParserCSV.Expense::.ctor()
            IL_0006:  ldarg.1
            IL_0007:  brtrue.s   IL_000a
            IL_0009:  ret
            IL_000a:  ldstr      "test"
            IL_000f:  call       void [mscorlib]System.Console::WriteLine(string)
            IL_0014:  ret
          }
          

          看到第 7 行的“差异”了吗? ;-) 编辑 - 使用 VS2010 在“发布”中编译

          【讨论】:

          • 我看到了区别(一个是针对真,另一个是假),但我并没有完全遵循 MSIL 的流程(阅读它时非常缺乏经验)。看起来后者评估为多一个“行”,因为有两个返回语句,但唯一的区别是 007 上的 GOTO?
          【解决方案6】:

          这完全取决于代码库的可读性和一致性。一个带有返回值的长方法将很难阅读(但无论如何,一个长方法是不好的)。方法开头的几个保护子句可以提高清晰度并消除不必要的嵌套。但是,在您给出的具体示例中,您必须问“为什么这里 null 可以?”您应该抛出异常,还是传入null objects

          【讨论】:

          • 在这种特定情况下,null 是可以的,因为它们是 asp.net mvc 中视图模型的便捷构造函数。如果来自服务层的数据库模型返回为空(创建版本的“保存”的可能性很大),则视图模型将为空白,这有助于通过始终实例化视图模型来减少控制器代码,无论是否数据库模型为空。
          【解决方案7】:

          可读性是最大的区别。在这种情况下,后者会减少缩进,有些人可能认为缩进更易读。我还认识一些开发人员,他们坚信方法应该只有一个 return 语句。那些开发者显然更喜欢前者。

          【讨论】:

            猜你喜欢
            • 2023-03-21
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-12-19
            • 2014-04-12
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多