Func vs. Predicate vs. Expression in C# .Net

Built-in Delegates in C# .Net

Jiyan Epözdemir
4 min readOct 5, 2024

In C#, delegates allow you to treat methods as variables, passing them around or assigning them to other methods. While learning about delegates, you may have come across custom delegates, where you define your own delegate types. If you’re unfamiliar with the basics of delegates, I recommend checking out my previous blog post on understanding delegates, where I cover how delegates work and why they’re useful.

In this post, we’ll focus on built-in delegates provided by C#, such asFunc, Predicate , Expression and Action. These predefined delegates are all used to encapsulate methods or expressions, but they serve different purposes and are used in different contexts.

Here's a breakdown of each:

Func

Func is a delegate that represents a method that returns a value. You can use it when you need a function that takes one or more inputs and gives you something back. It can take up to 16 parameters and always returns a value of the specified type.

It works for almost anything! but commonly used in LINQ and other functional programming patterns in .NET.

Syntax:

  • Func<TResult>: A method with no parameters and returns a TResult.
  • Func<T1, TResult>: A method that takes one parameter of type T1 and returns a TResult.

Look at the example below that converts an integer to a string :

Func<int, string> func = x => x.ToString();
string result = func(5); // "5"

Note that, Func takes an integer as input and returns a string equivalent as output.

Predicate

Predicate is a specialized delegate that represents a method that takes one parameter and always returns a bool, indicating whether the condition is met. Thus, it wouldn’t be wrong to describe it as a special type of Func that always returns a true or false.

Often used for methods that need to test a condition, like filtering items in a collection. You can use it when you need to check if something is true about a value, like “Is this number even?”

Syntax:

  • Predicate<T>: A method that takes a parameter of type T and returns a bool.

Here’s an example of Predicateusage that checks if an integer is even and returns true or false.

Predicate<int> isEven = x => x % 2 == 0;
bool isFiveEven = isEven(5); // false

Expression

Expression is a class used to represent code as data, specifically expressions that can be compiled to executable code or converted to other forms, such as SQL queries in LINQ-to-SQL. I mean, it doesn't just run a method; it can be inspected or even turned into something else.

It builds an “expression tree” that can be looked at or changed before running instead of executing code right away. Then returns that expression tree as a result that can be compiled to a delegate or traversed for analysis.

On that sense, we can say that Expression is a bit more powerful than the others.

Often used in scenarios where the expression needs to be analyzed or transformed before being executed, like in ORM tools or LINQ providers.

Syntax:

  • Expression<Func<T, TResult>>: Represents a lambda expression that can be compiled or interpreted.

Following code snippet represents an expression that checks if an integer is greater than 10 :

Expression<Func<int, bool>> expr = x => x > 10;
// You can compile and run this expression:
Func<int, bool> compiledExpr = expr.Compile();
bool isElevenGreaterThanTen = compiledExpr(11); // true

Comparison & Use Cases

Func vs Predicate:

  • Use Func when you need to return any type of value.
  • Use Predicate when you specifically need to return a boolean value and check a condition. I mean; you need to just checking if something is true or false.

Func/Predicate vs Expression:

  • Use Func or Predicate when you need to directly execute a delegate.
  • Use Expression when you need to inspect, modify, or compile the logic before executing it. Expression is particularly useful in scenarios where the code needs to be translated, like building dynamic queries or converting it to SQL in LINQ.

BONUS: Action

Yeah, there is another built-in delegate called Action. I couldn’t miss that :)

Action is similar to Func, but it does not return any value. It’s used to pass methods that perform an action or some logic but don't need to give anything back (i.e. return void).

Look at example below, Action takes a string input but doesn't return anything. It just performs the Console.WriteLine() operation.

// Prints "Print action called!" to the console
Action<string> print = message => Console.WriteLine(message);
print("Print action called!");

As summary, each of these delegates serves a specific purpose in .NET, and understanding their differences allows you to choose the right one for your particular scenario.

Thank you for reading!

If you found this post helpful, don’t forget to give it a clap and share it with others who might benefit from it.👏👏👏👏👏

--

--

Jiyan Epözdemir
Jiyan Epözdemir

Written by Jiyan Epözdemir

I am a multi-disciplined Software Architect and Computer Engineer, MSc. I enjoy building awesome softwares & applications.

Responses (3)