A few LINQ methods (like Where
and Select
) are deferred because computing one result is independent from computing the next result. But not all methods that operate on an IEnumerable<T>
are necessarily deferred.
For example, Sum
will reduce all elements of the sequence into one. As such, it can compute nothing at all or everything, but there's no way to do anything in-between. Its authors chose to break their usual LINQ habit and they made it compute eagerly rather than lazily.
This is proven by the fact that Sum
on an IEnumerable<int>
has a return type of int
, which is an already calculated integer:
int res2 = no.Sum(a => a * a);
If you want to defer the calculation of Sum
, there's a simple way -- use a Func<int>
:
Func<int> res2 = () => no.Sum(a => a * a);
Alternatively, you can make it a LINQ-like extension method:
public static Func<int> LazySum(this IEnumerable<int> sequence, Func<int, int> selector)
=> () => sequence.Sum(selector);
And then use it like this:
var res2 = no.LazySum(a => a * a);
Regardless of which one you choose, you can verify that it will give you deferred computation:
Console.WriteLine(res2()); // prints 55
no.Add(100);
Console.WriteLine(res2()); // prints 10055