C# 快速退出方法或构造函数是否有好处?

C# 快速退出方法或构造函数是否有好处?,c#,constructor,short-circuiting,C#,Constructor,Short Circuiting,我相信这部分与短路逻辑有关,但我找不到任何直接回答我问题的问题。可能的相关问题: 考虑以下两个代码块,它们都是类的可能构造函数 public MyClass(OtherClass other){ if (other != null) { //do something with other, possibly default values in this object } } 还有这个 public MyClass(OtherClass other){ if

我相信这部分与短路逻辑有关,但我找不到任何直接回答我问题的问题。可能的相关问题:

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

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?
的函数,如果该值为
null
偶数
,或大于100,则该函数将退出

你可以

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

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

这都是关于代码库中的可读性和一致性。如果一个长方法的返回值到处都是,那么它将很难被读取(但是一个长方法无论如何都是不好的)。方法开头的几个保护子句可以提高清晰度并删除不必要的嵌套。然而,在您给出的特定示例中,您必须询问“为什么这里可以使用null?”您应该抛出异常还是传入异常?

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

特别是在这种情况下,虽然您(假设您是人类)需要通读其余的源代码才能完成方法,但处理器不需要。第一个示例中的block
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行的“差异”;-)
编辑-使用VS2010在“发布”中编译这也是我的想法。只是想看看这样做是否有性能(或任何其他)优势。在这个特定的例子中,null是可以的,因为它们是asp.net mvc中视图模型的方便构造函数。如果来自服务层的数据库模型返回为null(创建“Save”版本的可能性很大),那么视图模型将为空,这有助于通过始终实例化视图模型来减少控制器代码,而不管数据库模型是否为null。我看到了差异(一个是对true的评估,另一个是对false的评估),但是我在这里并不完全遵循MSIL的流程(在阅读它方面相当缺乏经验)。看起来后者的计算结果又多了一行,因为有两个返回语句,但唯一的区别是007上的GOTO?
.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
}