Higher Order Function Examples
This article illustrates how to replace explicit loops with higher-order functions in a generic, functional programming style using C#. The examples below demonstrate converting a simple for-loop into more expressive and reusable functions.
Converting For Loops into a Higher-Order Function
Consider the following imperative approach to process an array of items:
This loop explicitly controls the iteration over the array, updating mutable variables along the way. To simplify and make the code more declarative, many languages offer the foreach statement:
The foreach statement abstracts the iteration details (like index incrementation), making the code more concise and easier to maintain.
We can further improve this by defining a higher-order extension method called ForEach, which encapsulates the iteration logic:
Here, Action<T> is a delegate representing a method that takes a single argument of type T and returns void. With this extension method, we can now write:
Or even chain multiple operations:
The .NET framework also includes a similar ForEach method on List<T>, but defining it as an extension method for arrays (or any IEnumerable<T>) offers greater flexibility.
Returning Functions from Functions
In functional programming, functions are first-class objects, meaning they can be passed as arguments, returned as values, and assigned to variables. In C#, delegates such as Action allow you to treat methods as first-class objects.
For example, consider a higher-order function that wraps another function with error logging:
This WrapLogging function takes an Action as input and returns a new Action that executes the original action within a try-catch block. You can use it as follows:
Deferred execution here means that the wrapped function isn’t executed until you explicitly invoke the returned delegate.
Partial Application
Partial application is the process of fixing a few arguments of a function, producing another function with fewer parameters. For example, we can create a function that always adds a fixed value to its input:
In this example, calling MakeAdder(5) returns a function that adds 5 to any number, effectively "partially applying" the value 5.
Summary
In this article, we explored several functional programming techniques in C#:
Higher-order functions: Replace explicit loops with reusable methods like
ForEach.Returning functions: Wrap functions with additional behavior (e.g., logging) by returning new delegates.
Partial application: Create new functions by fixing some arguments of a function.
These approaches promote more declarative, concise, and maintainable code compared to traditional imperative loops, reducing repetition and minimizing errors.
See Also: