C# 3.0 Higher Order Functions


I’ve been reading a lot about F# and functional programming, and it has indeed been pretty head-turning but it’s really powerful if you know how to use it. Type Inference in F# compiler is spectacular compared to the C# one, but I shall not digress. This post is about showing off the functional aspects of C# 3.0, namely Higher Order Functions. In short, higher order functions are functions that can take in one or more functions as input parameters, as well as return a function as an output. In C# 3.0, delegates have evolved a lot and with the introduction of the System.LINQ namespace, plus a lot of functional features have been incorporated into the language, and we’ll see how to make full use of them.

In the System.LINQ namespace, you will find a large bunch of Extension Methods for IEnumerable<T> class. Most of them are higher order functions, meaning that they take in a delegate (or pointer to a function) as an input parameter. Some of these delegate types taken as inputs are Func<T, TResult>, Action<T> and Predicate<T>. What this means is that you can pass in an Anonymous Function (Lambda Expressions and Anonymous Methods) to enable different kind of behaviors. If you’re familiar with the Strategy Pattern, programmers use this pattern in order to “plug in” different behaviors flexibly by writing a family of algorithms encapsulated within derived strategy classes. With higher order functions, I’m inclined to believe that we now have something more straightforward and powerful at our disposal.

Higher Order Functions

Consider this Department class…

public class Department
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int NoOfEmployees { get; set; }
}

In your project, add a “using System.Linq;” and all the IEnumerable<T> extension methods will show up in Intellisense. Below are some example of how to use some of these higher order functions with lambda expressions.

  // create new list of departments
  List<Department> departments = new List<Department>(
    new Department[] { new Department { Id = 1, Name = "IT", NoOfEmployees = 200 },
    new Department { Id = 2, Name = "Delivery", NoOfEmployees = 10 },
    new Department { Id = 3, Name = "HR", NoOfEmployees = 34 },
    new Department { Id = 4, Name = "Accounts", NoOfEmployees = 43 } });

  // return number of departments with more than 30 employees
  var noOfDepartmentsGreaterThan30 = departments.Count(d => d.NoOfEmployees > 30);   

  // calculate average number of employees
  double average = departments.Average(d => d.NoOfEmployees);    

  // find largest number of employees in departments
  int mostEmployees = departments.Max(d => d.NoOfEmployees);    

  // total number of employees
  int allEmployees = departments.Sum(d => d.NoOfEmployees);    

  // rearrange list to order by Name
  var orderByName = departments.OrderBy(d => d.Name);    

  // convert list to dictionary with ID as key and Name as value
  var dictionary = departments.ToDictionary(d => d.Id, d => d.Name);    

  // cut down all staff by 50% using projection
  var downSized = departments.Select( (d, index) =>
      new Department() { Id = d.Id, Name = d.Name, NoOfEmployees = d.NoOfEmployees / 2 });

As you can see, there’s a bunch of useful functions we can use, like finding average, finding total number of employees, finding the department with largest number of employees…etc. The beauty of using higher order functions is that you can swap behaviors easily, for example you can order a list by Department Name or Number of Employees just by simply modifying the lambda expression, thanks to Generics.

  // rearrange list to order by no of employees
  var orderByEmployeeNumbers = departments.OrderBy(d => d.NoOfEmployees);

You can even chain up functions to perform multiple actions, at the expense of readability though. Here we are finding all departments with more than 40 employees, selecting only the department names, and sorting them by name.

  // find all department names where employees count is greater than 40, and order by department name
  var names = departments.Where(d => d.NoOfEmployees > 40).Select(d => d.Name).OrderBy(s => s);

One interesting function I discovered is the Aggregate function. A function is applied to each element in your enumeration, and the result of the last call to the function is passed in as an argument to the next function call for the next element. This is somewhat similar to a recursive call. There are three overloads for this function, and I will be using the overload that optionally allows a seed value.

  // using an accumulator function to create a formatted string output displaying department name and size
  var result = departments.Aggregate(new { StartOfLine = true, StringResult = string.Empty },
    (r, department) =>
    {
      var departmentAndSize = string.Concat(department.Name, " : ", department.NoOfEmployees);
      var concat = r.StartOfLine ? departmentAndSize.PadRight(20) : string.Concat(departmentAndSize, "\n");
      return new { StartOfLine = !r.StartOfLine, StringResult = string.Concat(r.StringResult, concat) };
    });

  Console.WriteLine(result.StringResult);

For the seed value, I used an Anonymous Type as the input. Basically we are trying to format an output string using the Department Name and Number of Employees. The seed value type has a StartOfLine boolean value which we flip on every function call, and returned to be used as an argument for the next recursion. So we will PadRight by 20 to the output string or add a new line in an alternate fashion. The function returns the seed value type we specified as a return value, and I printed the output to Console.

aggregate_function_output

Extension Methods

The IEnumerable<T> higher order functions we have looked at so far are all extension methods. Let’s write an extension method for a List<T> that allows you to write all the List’s items to Console.

  public static class Extensions
  {
    public static void WriteLineToConsole<T>(this List<T> source, Func<T, string> elementSelector)
    {
      source.ForEach(t => Console.WriteLine(elementSelector(t)));
    }
  }

  // Calling the extension method
  departments.WriteLineToConsole(d => string.Concat(d.Name, " : ", d.NoOfEmployees));

As you can see, it’s pretty easy to create a higher order function using extension methods. So far we have looked at higher order functions that take in other functions as inputs, now let’s look at one that does both. I’d like to look at it as a composition of functions. For example, let’s dissect this extension method.

  public static Func<X, Z> Compose<X, Y, Z>(this Func<X, Y> f, Func<Y, Z> g)
  {
    return (x) => g(f(x));
  }

We’ve created a generic extension method for Func<X,Y> which takes in another Func<Y,Z>. Func<Y,Z> g takes in as input a value of Type Y (which is the output of Func<X,Y> f), and returns an output of Func<X,Z >. Let’s see how we can apply this.

  List<int> integers = new List<int>(new int[] { 1, 2, 3, 4, 5, 6, 7, 8 });
  Func<int, int> square = (x) => x * x;
  var squareThenSum = integers.Select(square.Compose( y => y + y));
   // output: 2, 8, 18, 32, 50, 72, 98, 128 

First we create a List of integers. Next we declare a Func<int, int> called square, which basically squares the input. Next we can call the Compose extension method, which we pass into a lambda expression that adds the input  to itself, and returns a output of Func<int, int>. The output of the extension method is used by the Select extension method which basically projects the composite function onto all the items.

I hope this post has helped you obtain a stronger grasp of the power of functional programming in C#. I’m sure you will agree with me that it’s declarative nature makes it so much more elegant and being able to do much more in less lines makes it more readable. Enjoy…

Share this post :
Advertisements

3 Responses to “C# 3.0 Higher Order Functions”

  1. Tormod Fjeldskår Says:

    Great introductory read to functional programming in C#. Really shows how useful this paradigm can be, even in an object-oriented context.

  2. Jeff Says:

    This is very cool. Thanks!


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: