Wednesday, June 27, 2007

Today, I want to take a brief detour from our excursions into C# 2.0 and examine the C# 3.0 example from my recent article on higher-order functions:

static void Main()
{
  int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };

  int sum = numbers.Filter(x => (x % 2) == 0).Map(x => x * x).Reduce(0, (x, y) => x + y);

  Console
.WriteLine("Sum: {0}", sum);
}

The calculation being performed (summing the squares of the even numbers in an array) is not complicated, but I want to clarify that we don't actually have to define Filter, Map and Reduce in C# 3.0. While those names might be familiar to functional programmers, they already have equivalents in the .NET Framework 3.5.

  1. Filter = Where
  2. Map = Select
  3. Reduce = Aggregate

Each of these are implemented as extension methods for IEnumerable<T>. So, we can rewrite the code like this:

static void Main()
{
  var numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };

  var sum = numbers.Where(x => (x % 2) == 0).Select(x => x * x).Aggregate(0, (x, y) => x + y);

  Console
.WriteLine("Sum: {0}", sum);
}

The Aggregate method is a powerful way to create custom accumulations from an IEnumerable<T>. However, the .NET Framework 3.5 also provides several methods for common accumulations (e.g. Sum, Average, Count, Min, Max). In this situation, we could just use the Sum method.

static void Main()
{
  var numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };

  var sum = numbers.Where(x => (x % 2) == 0).Select(x => x * x).Sum();

  Console
.WriteLine("Sum: {0}", sum);
}

Finally, C# 3.0 provides a natural way to express the Where and Select calls using a query expression.

static void Main()
{
  var numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };

  var sum = (from n in numbers
             where (n % 2) == 0
             select n * n).Sum();

  Console
.WriteLine("Sum: {0}", sum);
}

While defining Filter, Map and Reduce are useful in C# 2.0, they are redundant in C# 3.0. We can use features already present instead of reinventing the wheel.

Have fun!

posted on Wednesday, June 27, 2007 11:54:58 AM (Pacific Standard Time, UTC-08:00)  #    Comments [6]

kick it on DotNetKicks.com