tags:

views:

40

answers:

3

Why only one overload throws this exception?

Little update: I understand that there was a design decision made by framework developers. The question is really why that decision has been made, is there a related design pattern or whatever? Because if I was designing that I'd return default(TSource). What is wrong with such approach?

+2  A: 

The other two overloads provide an initial, seed, value. With a seed value, the aggregation has something to return even when the source is empty.

Sam
why they cannot just return detault<TSource>? like in SQL where [select sum(a) from empty_table] returns null if that table is empty.
the_joric
@the_joric: Obviously, they *could* have; they made a design decision, and that decision was to throw an exception. As a developer you therefore know to check `if (values.Any())` before calling `values.Aggregate(...)`.
Dan Tao
I agree with Dan Tau that it was a design design, but would also not that callers have the option to use the overload that has a seed value if it's possible the source is empty.
Sam
The problem is `default(T)` will often be null, which could a `NullReferenceException` if the user is expecting there to always be a value (since the overloads that include a seed always have a value). It would still be different behavior from the other two overloads, in that you still need an extra check (a null check instead of an Any check), but NREs are typically more difficult to track down than exceptions that throw from where the problem is coming from.
Tanzelax
+2  A: 

The version of Aggregate<TSource> you are referring to is Aggregate<TSource>(this IEnumerable<TSource> enumerable).

This particular overload of aggregate is the only one which does not contain a seed (read starting value) for the aggregate operation. This creates an interesting case when the enumeration contains no elements. The method could do one of the following

  • Throw an exception alerting the user to the issue
  • Return default(TSource)

The author of the library chose to do the first one. Why I don't specifically know but likely because it was viewed as an ambiguity and it's best to make ambiguities loud vs. succeed (possible incorrectly) silently

The other two overloads have no issue because they have a seed / initial value which can be returned.

JaredPar
A: 

The one overload that throws the exception takes arguments of type IEnumerable<TSource> (this) and Func<TSource, TSource, TSource>. It starts with the first value and accumulates from there. Without a first value (if source is empty), there's no way for the function to know what to return.

The other two overloads accept an argument of type TAccumulate to act as the seed. Even if source is empty in this case, the function can simply return the seed value.

Dan Tao