为什么 post-increment 在 .Aggregate(...) 中失败但 pre-increment 成功?

Why does post-increment fail in .Aggregate(...) but pre-increment succeeds?

我正在摆弄我的项目欧拉答案之一,试图让它变得有点 shorter/cleaner/succinct。

我想到了这个:

Sequences.FibonacciBig() // infinite fib sequence of type BigInteger
    .TakeWhile(f => f.ToString().Length < 1000)
    .Aggregate(1, (i, _) => i++);

我的测试失败了,因为实际是 1,这看起来很奇怪。我首先想到的是懒惰的枚举没有被评估或类似的东西。我用 i += 1 代替,它起作用了,测试通过了。然后我用 ++i 替换它仍然有效。

我很困惑为什么在使用 post-increment 运算符时似乎根本没有对语句求值。在最坏的情况下,我预计会出现某种差一错误,但聚合函数实际上什么都不做。

谁能解释一下?

看下面的代码:

private int value = 0;

public int GetValue()
{
    return value++;
}

您希望它在第一次调用时 return 1 吗?它没有。它 return 是 value 的当前值,然后递增它。您的 lambda 表达式也会发生同样的情况。

.Aggregate(1, (i, _) => i++);

它 return 是 i 的当前值,然后递增它(这在这一点上毫无意义,因为您没有在其他任何地方引用它)。

pre-increment 和 += 之所以有效,是因为它们在 returning 之前增加了值。

i++ 作为副作用增加了 i,但是 i++ 表达式的 value 将是值 before i 递增,与 ++i 不同,后者的值将是 i after 的值。

换句话说:

var i = 3;
var a = i++;
Console.WriteLine("a = {0}, i = {1}", a, i); // a = 3, i = 4

将此与以下内容进行比较:

var i = 3;
var a = ++i;
Console.WriteLine("a = {0}, i = {1}", a, i); // a = 4, i = 4

但无论如何,这在这里并不重要,因为 你不应该在你的代码中增加 i 无论如何。你可以只写:

.Aggregate(1, (i, _) => i + 1)

因为i是一个参数,所以它只是一个局部变量,你以后不会重用。

但是,实际上,您为什么不直接写 .Count() + 1 呢?因为这正是您的 Aggregate 调用所做的...