2012-03-28 111 views
4

我相信这部分与短路逻辑有关,但我找不到任何直接回答我的问题的问题。可能的相关问题: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对象构造此代码的代码。

回答

6

这种情况下,你应该做什么是你和你的同事最可读的。这两种方法之间不可能有任何可感知的速度差异。

+0

这也是我的想法。只是想看看是否有一个表现(或任何其他)的好处,以一种方式做对比。 – 2012-03-28 16:55:15

4

唯一的区别是可读性。用你所谓的“快速退出”,你可以停止考虑你内在的条件,因为你不再是一个内在的。

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 

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

0

这完全取决于代码库中的可读性和一致性。一个很长的方法与返回洒在它将很难阅读(但一个很长的方法是坏的无论如何)。该方法开始时的一些警卫条款可以提高清晰度并消除不必要的嵌套。然而,在你给出的具体例子中,你不得不问“为什么这里是空的?”你应该抛出一个异常,还是通过null objects来代替?

+0

在这个特定的情况下,null是好的,因为它们是asp.net mvc中视图模型的便利构造函数。如果来自服务层的数据库模型返回为空(创建“Save”版本的可能性很大),则视图模型将为空白,这有助于通过始终实例化视图模型来减少Controller代码,而不管是否数据库模型为空。 – 2012-03-28 17:23:18

0

可读性是最大的区别。在这种情况下,后者会减少缩进,有些人可能会认为它更具可读性。我也知道一些开发者坚信方法应该只有一个返回语句。那些开发者显然更喜欢前者。

1

特别针对这种情况,虽然(假设你是人类)需要通读源代码的其余部分才能结束该方法,但处理器不会。第一个示例中的if语句块评估条件,如果它的计算结果为false,则执行跳转到该方法的末尾。

1

我试着用此构造

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中编辑'Release'

+0

我看到了不同(其中一个是对真实的评估,另一个是假的),但我并不完全遵循MSIL的流程(在阅读时很缺乏经验)。它看起来像后者评估到一个更“线”,因为这两个返回语句,但唯一的区别是007上的GOTO? – 2012-03-28 17:25:29

相关问题