快速退出方法或构造函数有好处吗

本文关键字:构造函数 退出 方法 | 更新日期: 2023-09-27 18:29:21

我相信这部分与短路逻辑有关,但我找不到任何直接回答我问题的问题。可能的相关问题:使用短路评估的好处,为什么使用短路代码?

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

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对象构造此对象的代码。

快速退出方法或构造函数有好处吗

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

唯一的区别是可读性。通过你所说的"快速退出",你可以停止思考你处于什么条件下,因为你不再处于其中。

后者通常更容易阅读,如果您有多个案例要终止,那么它会变得更容易。不过速度没有差别。

假设您有一个接收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

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

特别是在这种情况下,虽然(假设您是人类)需要通读源代码的其余部分才能到达方法的末尾,但处理器没有。第一个示例中的块if语句计算条件,如果计算结果为false,则执行将跳到方法的末尾。

我尝试过这个构造函数

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行的"差异"了吗?;-)edit-使用VS2010 在"Release"中编译

这一切都与代码库中的可读性和一致性有关。一个到处都是返回的长方法将很难阅读(但长方法无论如何都是糟糕的)。在方法开始时使用几个保护子句可以提高清晰度并消除不必要的嵌套。然而,在您给出的特定示例中,您必须问"为什么这里的null可以?"您应该抛出异常,还是传入null对象?

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