开发者

What is the reason for InvalidOperationException in Enumerable.Aggregate<TSource>?

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 wh开发者_JS百科y 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?


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.


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.


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.


Update: You ask why the decision was made not to simply use default(T) in the case of an empty sequence. The answer doesn't boil down to any specific pattern or known idiom, but rather simply to what is (in my opinion) the sensible choice in terms of API design. The point of Aggregate is to make it easy for developers to implement calculations for their own domain-specific problems, without making assumptions about the semantics of those calculations.

To use default(T) in the case of an empty sequence would be making not one but two pretty big assumptions:

  • that this calculation should produce a meaningful result in the case of an empty sequence; and
  • that this result should be default(T)

As a trivial counter-example to the first assumption, let's say I use Aggregate to compute the mode of a sequence of integers. This should give me the value occurring most frequently in the sequence, so a result of zero would simply be false (since the value 0 never occurs in an empty sequence).

As a counter-example to the second, suppose I take the product of reciprocals of a sequence of positive integers:

Aggregate [1, 2, 3, ...] -> 1 * 1/2 * 1/3 * ...

In this case the result would actually approach zero as the sequence gets larger, so a default value of zero would, again, be completely misleading.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜