为什么.Aggregate(...)中的后递增失败但是预递增成功?

时间:2015-03-10 23:32:29

标签: c# linq aggregate reduce

我正在摆弄我的一个项目欧拉答案,试着让它更短/更清洁/简洁。

我想出了这个:

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

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

我很困惑为什么在使用后增量运算符时根本不会对语句进行求值。在最坏的情况下,我预计会出现某种一对一的错误,但不会使聚合函数无效地执行任何操作。

有人可以解释一下吗?

2 个答案:

答案 0 :(得分:3)

请看以下代码:

private int value = 0;

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

您是否希望它在第一次调用时返回1?它没有。它返回value的当前值,然后递增它。你的lambda表达式也是如此。

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

它返回i的当前值,然后递增它(在那一点没有意义,因为你并没有在其他任何地方保持对它的引用。)

预增量和+=有效,因为它们在返回之前递增值。

答案 1 :(得分:1)

i++增加i作为副作用,但i++表达式的将是之前的值 {与i不同,{1}}会增加,其中值将是增量后++i 的值。

换句话说:

i

将其与:

进行比较
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电话所做的......