If you have been programming for any length of time, you may well have come across higher-order functions but (like me) may not have fully appreciated just how powerful they can be. If you've not heard of them before, never fear. I have an explanation below. What are higher-order functions? Simply put, a higher-order function is a function whose input or output is also a function. In the following example, the Map function takes a list of a particular data type and a function. It returns a new list with the function applied to each of the elements in the list (basically equivalent to the LINQs Select method). // definition List<TOut> Map<TIn, TOut>(List<TIn> list, Func<TIn, TOut> mapper) { var newList = new List<TOut>(); foreach (var item in list) { var newItem = mapper(item); newList.Add(newItem); } return newList; } // usage var myList = new List<int> { 1, 2, 3, 4, 5 }; int multiplyBy2 (int num) => num * 2; var multipliedList = Map(myList, multiplyBy2); // output { 2, 4, 6, 8, 10 }; bool isEven (int num) => num % 2 == 0; var isEvenList = Map(myList, isEven); // output { false, true, false, true, false }; Here is an example of a higher-order function that returns a function. First, you call the Add function with a given integer, which returns a function that adds that first integer to any given other integer. Func<int, int> Add(int a) => (int b) => a + b; var add9 = Add(9); var sum1 = add9(1); // output 10 var sum2 = add9(2); // output 11 Hopefully, by now, you can see why higher-order functions are so useful; they allow complex code to be reused in a highly flexible way by letting the client define their own input/output functions. For example, without using higher-order functions, one would have to define a new Map function for every type of mapping they needed. Practical Example - Repository Pattern The repository pattern is a very common design pattern used as a data access abstraction. It allows you to perform your typical CRUD operations without the client having to interact directly with the data provider. A typical repository interface may look something like this: public interface IProductRepository { int Create(Product product); bool Update(Product product); bool Delete(int id); Product GetById(int id); IEnumerable<Product> GetAll(); IEnumerable<Product> GetByCategoryId(int categoryId); IEnumerable<Product> GetActive(); // etc... } As you can see in this typical example, there are numerous definitions that all return . Every time you need another specific type of product filter, that requires adding to the interface and writing an entirely new implementation. That's not great for maintainability... IEnumerable<Product> Instead, using higher-order functions, we can define a single method that gets that takes a filter function as an input. That way, the client is free to define their own filters, and the ProductRepository doesn't need to keep being updated with new implementations. IEnumerable<Product> interface IProductRepository { // create, update, delete omitted IEnumerable<Product> Get(Func<Product, bool> filter = null); } public class ProductRepository : IProductRepository { private readonly List<Product> _products = new List<Product>(); // data source public IEnumerable<Product> Get(Func<Product, bool> filter = null) { // typically you might use the LINQ Where method here // but using the foreach to be clear what is happening if (filter is null) return _products; var filteredList = new List<Product>(); foreach(var product in _products) { if(filter(product)) { filteredList.Add(product); } } return filteredList; } } // client code var allProducts = _productRepository.Get(); var productsByCategoryId = _productRepository.Get(p => p.CategoryId == 1); var activeProducts = _productRepository.Get(p => p.Active); Conclusion In this article, I have introduced the concepts of higher-order functions and demonstrated how they are extremely useful in creating reusable and flexible code that is easy to maintain and understand. I have also given a practical use case that you may find in a .NET enterprise application - making the repository pattern more reusable. I post mostly about full-stack .NET and Vue web development. To make sure that you don't miss out on any posts, please follow this blog and . If you found this post helpful, please like it and share it. You can also find me on . subscribe to my newsletter Twitter Also published on . https://samwalpole.com/a-practical-guide-to-higher-order-functions-in-c