多个if块还是一个带AND条件的单个if块?

4
如果我需要检查多个条件,就性能而言,哪种方式更受推荐?
if( CND1 && CND2 && CND3 && CND4)
{
}
else
{
}

或者

  if(CND1)
{
   if(CND2)
   {
      if(CND3)
      {
         if(CND4)
         {
         }
         else
         {
         }
      }
      else
      {
      }
   }  
else
   {
   }
}
    }

1
if循环?我以为if是一个条件,而不是一个循环 ;) - knittl
1
你正在比较两种不同类型的条件。在第二个例子中,你会把 else 放在哪里? - Prutswonder
@Ram:如果您能在这里指定语言(或至少是语言家族),那将非常有帮助-请参阅nickf答案的评论。 - Jon Skeet
@Prutswonder - 对于造成的困扰我很抱歉。我对性能方面感到好奇,所以忽视了else部分。我现在已经添加了它。谢谢你的评论。 - Ram
4个回答

5

由于它采用了短路技术(即在找到假参数后就停止检查),因此性能是相同的,因此一定要选择第一个选项。与其他10行代码相比,仅需一行代码。这也意味着您的else语句将更容易处理。


@Johannes:在一个没有短路的语言中,这两个版本本来就不等价——评估(比如)CND2 的任何副作用都会在第一个版本的每种情况下被观察到,但在第二个版本中则不会。我相当自信地假设这里使用了短路。 - Jon Skeet
@Johannes,这个问题最初不是标记为C#的吗? - Mark Booth
@Jon Skeet,看看我的回答,了解为什么在某些语言中可能会存在性能差异的原因。虽然不完全是@nickf所想象的那样。*8') - Mark Booth
@Mark:正如我所说,我假设这是一种具有短路功能的编程语言,否则它们本来就不是等价的。 - Jon Skeet
@Mark:不,当时只有“coding-style”作为标签。 - Joey

4
他们在性能方面是相同的,但我认为第一种形式更易读。
我会将条件分开的唯一情况是存在逻辑条件集合。
if (x && y) // x and y are related
{
   if (a && b) // a and b are related
   {
   }
}

虽然有一个更易读的替代方案(但是必须承认它会评估更多的条件):

bool shouldPayBackDebt = x && y;
bool haveEnoughFunds = a && b;
if (shouldPayBackDebt && haveEnoughFunds)
{
    // ...
}

1
+1 我喜欢你提到的第二种方法。我会说,当性能几乎可以忽略不计时,始终选择最易读的方法。 - Dan Diplo

1

就性能而言,它们是相同的。&&是短路运算符,所以如果CND1为假,则不会评估其余部分。


1

C#使用短路求值,因此从性能上来看,两者应该是相同的。

在一个没有短路求值的语言中,后者可能会更有效率,但是像所有的优化一样,您应该进行基准测试以查看是否存在性能提升,并决定是否值得使代码变得更加复杂和难以维护。

此外,这种“优化”实际上可能并不是一种优化。如果条件很便宜,而额外的复杂性增加了代码的大小,使其现在(例如)不再适合缓存,那么它实际上可能表现得更差!

从编码风格的角度来看,这应该真正取决于您想要对else做什么。如果您希望在所有条件都为真时执行一件事情,在任何条件为假时执行另一件事情,请选择前者。如果您想要根据哪些条件为假来执行不同的操作,则使用后者。

这不仅仅是风格问题,而是关于你想要实现什么。但如果你确实想要在任何一个条件为 false 的情况下做同样的事情,你应该使用第一种形式,这样就不会在每个 else 块中重复相同的代码。如果有疑问,在给定两种实现相同需求的方式时,选择最简单、最清晰、最易维护的选项总是个好主意。

哦,以防你不知道,如果你想在 C# 中急切地评估条件,可以使用 &| 而不是 &&||。所以,如果你想让所有条件都运行(可能是为了副作用),你可以这样做:

if (CND1 & CND2 & CND3 & CND4) { // Eagerly evaluate all conditions.
    ...
}
else {
    ...
}

然而,这里需要记住的一件事是,这看起来非常类似于短路版本,因此值得评论它,特别是如果C或C ++人员可能会查看代码。

另外,我发现以下懒惰结构非常有用:

ok = ok && CND;

但是严格等效看起来太相似了:

ok = ok & CND;

因此,我确保像这样的代码被重构为:

ok &= CND;

这使得行为上的差异更加明显。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接