I was recently reading Programming Ruby: The Pragmatic Programmers’ Guide, Second Edition, and came across this piece of example Ruby code:

[1,3,5,7].inject(0) {|sum, element| sum+element} -> 16
[1,3,5,7].inject(1) {|product, element| product*element} -> 105

Inject is a method which acts on an array by aggregating or accumulating the values within that array. It loops through the array, and for every item in the array, it performs a function. It then saves the result for the next iteration of the loop and eventually returns the aggregated value.

In C# 1.0 you would probably write such a method like this:

int sum = 0;
int[] list = new int[] { 1, 3, 5, 7 };
foreach (int item in list)
{
  // Perform some function, then save the result
  sum = sum + item;
}

It’s a bit long-winded, and if you wanted to make it reusable, you’d have a hard time.

In C# 3.0, you can do it just like you can in Ruby.

Defining the Aggregation

First, let me explain how the Ruby inject method works.

First of all, it’s really misnamed in Ruby. The method is an aggregator, or even an "accumulator". It aggregates or accumulates values. It takes two parameters - a starter value, and a block. In C# 3.0 we basically call a block a delegate, although in this case, it’s more like a Lambda Expression.

The inject method works like this:

  1. it takes the starter parameter and sets the aggregated value (the sum in the above example) to its value.
  2. For the first item in the array, it passes the tarter value and the item itself to the block, which then performs the defined function on it.
  3. The return value from the block is then assigned to the running aggregated value.
  4. The running aggregated value is passed into the next iteration with the next item from the list. The function is called on those items again.
  5. When the method has iterated over all items in the list, it returns the aggregated value.

Moving to C# 2.0

So, let’s imagine you were trying to write the Inject method in C# 2.0. If you were to refactor the above C# 1.0 example as C# 2.0, you might use anonymous methods to write this:

// Define a delegate
delegate int Aggregator(int sum, int item);

static void Main(string[] args) {

  int sum = 0;
  int[] list = new int[] { 1, 3, 5, 7 };

  sum = Inject(sum, list,     delegate(int starterVal, int item) {
      return starterVal + item;
    });
}

int Inject(int starterVal, int[] list,
           Aggregator aggregator) {
  int sum = starterVal;
  foreach (int item in list) {
    // Perform some function, then save the result
    sum = aggregator(sum, item);
  }
  return sum;

However, that would only work for int objects. You could really make it generic, and use the same method for other types:

// Define a delegate
delegate T Aggregator<T>(T sum, T item);

  sum = Inject<int>(sum, list,
     delegate(int starterVal, int item) {
      return starterVal + item;
    });

...

T Inject<T>(T starterVal, T[] list,
  Aggregator<T> aggregator) {
  T sum = starterVal;
  foreach (T item in list) {
    // Perform some function, then save the result
    sum = aggregator(sum, item);
  }
  return sum;
}

It’s nicer, but the Ruby method still wins hands-down for neatness.

Move Over Ruby, Here Comes C# 3.0

The good news is, the C# 3.0 compiler and the .Net 3.5 framework can now take care of most of this for you.

To start with, the Aggregator delegate is no longer necessary, because the new Func<T,T,T> delegate already defines a generic delegate which returns a value.

T Inject<T>(T starterVal, T[] list, Func<T,T,T> aggregator)

Secondly, the anonymous function using the delegate keyword can be replaced by a lambda expression like this:

(starterVal, item) => starterVal + item

Thirdly, the Inject method can be defined as an extension method so that you can call it like this:

sum = list.Inject(sum, (starterVal, item) => starterVal + item );

And fourthly, the compiler can infer the type for you, so you don’t need to specify it on calling the method.

The Aggregate Method

But the even better news is that this method is already defined in the .Net framework for you, so you don’t even have to write it. Instead of being called inject, it’s called Aggregate, and is defined on the System.Linq.Enumerable<T> class.

So basically, using C# 3.0, you could reduce the above code to this:

var sum = 0;
var list = new[] { 1, 3, 5, 7 };
sum = list.Aggregate(sum,
                     (starterVal, item) => starterVal + item );

You get an extra bonus point if you spotted the extra C# 3.0 features I sneaked in there - the var keyword, and array initializers.

C# 3.0 is pretty neat huh? Move over Ruby.