Func vs Action vs Predicate in C#

In this post, I will explain the Func vs Action vs Predicate in C# difference. All of them delegates that allow you to define and pass around functions as parameters.

What is a Func?

A Func delegate represents a function that takes zero or more input parameters and returns a value. The last type parameter of the Func delegate represents the return type of the function. For instance, a Func<int, int, int> delegate represents a function that takes two integers as input parameters and returns an integer. Here is a simple example:

C#
Func<int, int, int> sum = (a, b) => a * b;
int result = sum(10, 10);
Console.WriteLine(result); // Outputs 100

Func examples

One of the most common uses of Func in C# is in LINQ (Language Integrated Query). The delegate is used to perform various operations over collections. For instance, we have a class City and a collection of cities:

C#
public class City
{
    public string Name { get; set; }

    public string Country { get; set; }

    public double Population { get; set; }
}

List<City> cities = new List<City>()
{
    new City() { Name = "Tokyo", Country = "Japan", PopulationInMln = 14 },
    new City() { Name = "New York", Country = "USA", PopulationInMln = 9 },
    new City() { Name = "Amsterdam", Country = "The Netherlands", PopulationInMln = 1 },
    new City() { Name = "Paris", Country = "France", PopulationInMln = 4 },
    new City() { Name = "Athens", Country = "Greece", PopulationInMln = 0.7 },
    new City() { Name = "Buenos Aires", Country = "Argentina", PopulationInMln = 3 }
};

You can use the Where LINQ extension method to filter on certain criteria. This method accepts a Func:

C#
Func<City, bool> filterCities = (city) => city.Name.StartsWith("A");
var filtered = cities.Where(filterCities);

// or directly

var filtered = cities.Where(c => c.Name.StartsWith("A"));

This will return all Cities starting with the letter “A”. You can use another extension method, called Select, to get specific properties of the City object. The Select also accepts a Func:

C#
Func<City, string> selectNames = (city) => city.Name;
Console.WriteLine(string.Join(", ", filtered.Select(selectNames))); // Outputs: Amsterdam, Athens

// or where and select combined:

var citiesWithA = cities
        .Where(c => c.Name.StartsWith("A"))
        .Select(c => c.Name);

And another Func example for calculating an average value over a collection:

C#
Func<City, double> averagePopulation = (city) => city.PopulationInMln;
var average = cities.Average(averagePopulation);
Console.WriteLine(average); // Outputs 5.28

What is an Action?

An Action delegate is similar to the Func except that it doesn’t return a value. It represents a function that takes zero or more input parameters and does not return a value.

Action examples

A good action example is the Linq.ForEach method. It iterates over each element in a collection:

C#
Action<City> printCities = c => Console.WriteLine(c.Name);
cities.ForEach(printCities);

// or directly

cities.ForEach(c => Console.WriteLine(c.Name));

The Action accepts a City object as a parameter, and performs some operation on it. In this example – just printing on the console.

What is a Predicate?

A Predicate is a delegate type that represents a method that takes one input parameter and returns a boolean value. The predicate delegate takes an input value and determines whether the value satisfies a certain condition. Then it returns true if the condition is met, or false if it is not.

Predicate examples

Predicates are often used in LINQ queries to filter collections of data based on a certain condition. For instance:

C#
Predicate<City> biggestCitiresPrediccate = c => c.PopulationInMln > 5;
var biggestCities = cities.FindAll(biggestCitiresPrediccate);
foreach (var city in biggestCities)
{
    Console.WriteLine(city.Name); // Outputs: Tokyo, New York
}

// or simple:

cities.FindAll(c => c.PopulationInMln > 5);

In this example, the predicate takes a City as a parameter and returns true if its population is larger than 5 million, otherwise – false.

Func vs Action vs Predicate in C# Summary

Func vs Action vs Predicate in C#
Func vs Action vs Predicate in C#