布尔AND不评估表达式的两侧

时间:2013-12-21 13:35:57

标签: c# boolean-expression side-effects

 class Program
 {
  static void Main(string[] args)
  {
   bool success = true;
   int[] array = { 10, 15, 20 };
   foreach (var i in array)
    success = success && SynchronizeAccount(i);
  }

  static bool SynchronizeAccount(int i)
  {
   Console.WriteLine(i);
   return false;
  }
 }

输出为10.在第一步之后,'success'变为false并且永远不会为true,因此c#在第一次迭代后停止循环执行。但是我需要SynchronizeAccount的SIDE效果,而不是'成功'值。

5 个答案:

答案 0 :(得分:18)

这不是一个错误,因为在几乎所有编程语言中C#懒惰地评估&& - 如果左操作数已经为假,则整个表达式永远不会变为真,因此不再需要它评估表达式的右操作数。

翻转操作数或更改为success & SynchronizeAccount以强制评估两个操作数。

请注意,它是C#的一个独特功能,您可以将&&&同时应用于布尔值 - 在大多数其他语言中包括Java和PHP一个&符号({{1} })是按位AND,它通常提供完全不同的结果。

答案 1 :(得分:8)

这不是错误,这是正常行为。如果左侧评估为true&& operator将仅评估运算符的右侧:

  

条件AND运算符(&&)执行其bool操作数的逻辑AND,但只在必要时才计算其第二个操作数。

因此,在第一次迭代后,success评估为false,并且SynchronizeAccount不再被调用。

如果您想评估SynchronizeAccount而不管其返回的内容,请改用& operator

foreach (var i in array)
    success = success & SynchronizeAccount(i);

或更简单:

foreach (var i in array)
    success &= SynchronizeAccount(i);

或者也许使用一点Linq:

bool success = array.Aggregate(true, (b, i) => b & SynchronizeAccount(i));

答案 2 :(得分:4)

这不是错误,它被称为 Short-circuit evaluation 。如果您确实需要使用第二种方法,我们&代替&&

答案 3 :(得分:1)

我不会将此视为一个错误;它看起来就像一个优化。 “&安培;&安培;”是短路的,因此如果不需要编译器,则允许编译器优化调用方法。

您可以尝试重写此内容,如


foreach (var i in array) {
  if(!SynchronizeAccount())
    success = false;
}

答案 4 :(得分:1)

考虑从循环中删除success

其他答案很适合解释& vs &&,但我不确定success在您的代码中的用途是什么。由于您打算忽略它并遍历array中的所有项目,只需在SynchronizeAccount循环内调用foreach并忽略返回的值。

static void Main(string[] args)
{
    int[] array = { 10, 15, 20 };
    foreach (var i in array)
        SynchronizeAccount(i);
}