Nicolas S.Xu
Nicolas S.Xu

Reputation: 14554

C# Aggregate function definition explanation

There are 3 overload versions of Enumerable.Aggregate. I couldn't find any overload version of this function to match the one used in official example.

public static TSource Aggregate<TSource>(
    this IEnumerable<TSource> source,
    Func<TSource, TSource, TSource> func
)

The above definition is totally different from this official example:

string sentence = "the quick brown fox jumps over the lazy dog";

// Split the string into individual words.
string[] words = sentence.Split(' ');

// Prepend each word to the beginning of the 
// new sentence to reverse the word order.
string reversed = words.Aggregate((workingSentence, next) =>
                                      next + " " + workingSentence);

Console.WriteLine(reversed);

// This code produces the following output:
//
// dog lazy the over jumps fox brown quick the 

Here are 3 overload versions of Aggregate function:

public static TSource Aggregate<TSource>(this IEnumerable<TSource> source, Func<TSource, TSource, TSource> func);

public static TAccumulate Aggregate<TSource, TAccumulate>(this IEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> func);

public static TResult Aggregate<TSource, TAccumulate, TResult>(this IEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> func, Func<TAccumulate, TResult> resultSelector);

None of them match the function used in the above example. Is the official document wrong? or I missed sth? Please help me bridge the gap between 3 versions of function definition and this official example.

How to understand the function definition?

Upvotes: 2

Views: 505

Answers (4)

Saeed Afshari
Saeed Afshari

Reputation: 949

The official document is completely correct. In the official example the following signature is used:

public static TSource Aggregate<TSource>(this IEnumerable<TSource> source, Func<TSource, TSource, TSource> func);

It is an extension method then string[] word as an array of string matches IEnumerable source. And the following code is match with Func func:

(workingSentence, next) => next + " " + workingSentence

In other words you can write:

Func<string, string, string> func = (workingSentence, next) => next + " " + workingSentence;
words.Aggregate(func);

Two first strings in func are input and the last one is the return value type that in this example is aggregation of two strings.

Upvotes: 1

StriplingWarrior
StriplingWarrior

Reputation: 156644

public static TSource Aggregate<TSource>(
    this IEnumerable<TSource> source,
    Func<TSource, TSource, TSource> func
)

This is actually the one used in the official example:

string reversed = words.Aggregate((workingSentence, next) =>
                                      next + " " + workingSentence);

Some pieces that might be confusing you are:

  1. the this keyword in front of the source parameter identifies it as an Extension method, which means the above code is syntax sugar for:

    string reversed = Enumerable.Aggregate(words, (workingSentence, next) =>
                                      next + " " + workingSentence);
    
  2. TSource is a generic parameter, which in this case is substituted with string because the compiler is able to infer this type from the fact that words is an IEnumerable<string>.

  3. Func<TSource, TSource, TSource> is a generic delegate representing a function that takes two parameters (the first two TSources), and returns a TSource. This is in contrast to Action<TSource, TSource>, which would take two parameters and not return a value. Either of these types can be represented with a lambda expression with the form (param1, param2) => expression.

Upvotes: 4

HiredMind
HiredMind

Reputation: 1857

The this modifier indicates that the overload is an Extension Method.

So in this case, this IEnumerable<TSource> source in the method definition corresponds to words in the example.

Upvotes: 1

Abion47
Abion47

Reputation: 24736

The example you gave uses the first overload you posted. It might be because it's an extension method that is throwing you off.

With an extension method, the this parameter becomes a reference to the instance that it is called on. When the code is compiled, it is translated into the proper static method call. Basically, when you write this:

words.Aggregate((workingSentence, next) =>
                                  next + " " + workingSentence);

It compiles into this:

Enumerable.Aggregate<string>(words, (workingSentence, next) =>
                                  next + " " + workingSentence);

Upvotes: 2

Related Questions