Question
In C#, what is the difference between Func<T, ...>, Action<T>, and Predicate<T> delegates, and when should each one be used?
Please explain them with practical, real examples so it is clear:
- When should I use a
Func<T, ...>delegate? - When should I use an
Action<T>delegate? - When should I use a
Predicate<T>delegate?
Short Answer
By the end of this page, you will understand that Func, Action, and Predicate are all delegate types in C# used to pass behavior as data. You will learn the key difference between them:
Funcreturns a valueActionperforms work and returns nothingPredicatereturnstrueorfalse
You will also see where they appear in real C# code, especially with collections, LINQ, validation, filtering, and callbacks.
Concept
In C#, a delegate is a type that can store a reference to a method. This lets you pass methods around like variables.
Func, Action, and Predicate are built-in generic delegate types that save you from creating custom delegates for common cases.
Action
Use Action when you want to do something but do not need a return value.
Examples:
- Print a message
- Log an error
- Update an object
- Send a notification
Action<string> print = message => Console.WriteLine(message);
print("Hello");
This means:
- input:
string - output: nothing (
void)
Func
Use Func when you want to calculate or transform something and return a result.
Examples:
- Convert text to uppercase
- Calculate tax
- Map one object into another
Mental Model
Think of these three delegate types as three kinds of workers:
Action: a worker who does a task and does not hand anything backFunc: a worker who takes input, processes it, and returns a resultPredicate: a worker who checks a rule and answers only yes or no
Another simple way to remember them:
Action= DoFunc= ComputePredicate= Check
If your method needs to answer a question with true or false, Predicate is a natural fit.
If your method produces any other kind of result, use Func.
If your method just performs work, use Action.
Syntax and Examples
Core syntax
Action<T>
Func<T, TResult>
Func<T1, T2, TResult>
Predicate<T>
Action example
Action<string> greet = name => Console.WriteLine($"Hello, {name}!");
greet("Sam");
Use this when you want to perform an operation and return nothing.
Func example
Func<string, int> getLength = text => text.Length;
Console.WriteLine(getLength("apple"));
This takes a string and returns an int.
Predicate example
Predicate<string> isLongWord = word => word.Length > 5;
Console.WriteLine(isLongWord("banana"));
This checks whether a string matches a condition.
Real collection examples
Action with
Step by Step Execution
Consider this example:
var names = new List<string> { "Ana", "David", "Li" };
Predicate<string> isShort = name => name.Length <= 3;
Func<string, string> makeUpper = name => name.ToUpper();
Action<string> print = text => Console.WriteLine(text);
var shortNames = names.FindAll(isShort);
var upperNames = shortNames.Select(makeUpper);
foreach (var name in upperNames)
{
print(name);
}
Step by step
- A list of names is created:
["Ana", "David", "Li"]
-
isShortis aPredicate<string>.- It checks whether a name has length
<= 3. - For each input, it returns
trueorfalse.
- It checks whether a name has length
-
is a .
Real World Use Cases
Action use cases
Use Action when code needs a callback that performs work:
- logging messages
- sending emails or notifications
- updating UI elements
- processing each item in a collection
- running custom code after a task finishes
void ProcessOrders(List<Order> orders, Action<Order> handleOrder)
{
foreach (var order in orders)
{
handleOrder(order);
}
}
Func use cases
Use Func when code needs a reusable calculation or transformation:
- formatting values
- converting DTOs to models
- computing totals
- generating keys or IDs
- selecting data in LINQ
Func<decimal, decimal> addTax = price => price * 1.2m;
Predicate use cases
Use Predicate when code needs a rule or test:
Real Codebase Usage
In real projects, these delegates often appear as small reusable pieces of business logic.
Validation and guard clauses
A Predicate<T> can hold a validation rule.
Predicate<string> isBlank = text => string.IsNullOrWhiteSpace(text);
if (isBlank(name))
{
throw new ArgumentException("Name is required.");
}
Transformation pipelines
A Func<T, TResult> is commonly used for mapping data.
Func<User, UserDto> toDto = user => new UserDto
{
Id = user.Id,
Name = user.Name
};
This is common in APIs and service layers.
Callbacks and side effects
An Action<T> is often passed into a method to customize behavior.
void ExecuteWithLogging(Action action)
{
Console.WriteLine("Starting...");
action();
Console.WriteLine("Finished.");
}
Filtering collections
While LINQ often uses Func<T, bool>, many collection APIs use directly.
Common Mistakes
1. Using Action when a return value is needed
Broken example:
Action<int, int> add = (a, b) => a + b;
This fails because Action must return void.
Correct:
Func<int, int, int> add = (a, b) => a + b;
2. Using Predicate<T> for non-boolean results
Broken example:
Predicate<int> doubleNumber = n => n * 2;
A Predicate<T> must return bool.
Correct:
Func<int, int> doubleNumber = n => n * 2;
3. Forgetting that Func's last type is the return type
Comparisons
| Delegate | Purpose | Returns | Common Use |
|---|---|---|---|
Action<T> | Perform work | void | Logging, printing, updating, callbacks |
Func<T, TResult> | Compute or transform | Any type | Mapping, calculations, LINQ Select |
Predicate<T> | Test a condition | bool | Filtering, validation, matching |
Predicate<T> vs Func<T, bool>
| Option |
|---|
Cheat Sheet
// Action: input(s), no return value
Action<string> log = message => Console.WriteLine(message);
Action<int, int> printSum = (a, b) => Console.WriteLine(a + b);
// Func: input(s), returns a value
Func<int, int> square = x => x * x;
Func<int, int, int> add = (a, b) => a + b;
Func<string, bool> isEmpty = text => string.IsNullOrEmpty(text);
// Predicate: one input, returns bool
Predicate<int> isPositive = x => x > 0;
Quick rules
ActionreturnsvoidFuncreturns a valuePredicatereturnsbool- In
Func<...>, the last type is the return type Predicate<T>is similar toFunc<T, bool>
Common API usage
List<T>.ForEach->
FAQ
What is the difference between Func and Action in C#?
Func returns a value. Action does not return anything and is used for work with side effects.
When should I use Predicate<T> instead of Func<T, bool>?
Use Predicate<T> when an API expects it, especially many List<T> methods. Use Func<T, bool> more often with LINQ.
Can a Predicate<T> have multiple input parameters?
No. Predicate<T> always takes one parameter of type T and returns bool.
Is Predicate<T> just a special case of Func<T, bool>?
Conceptually, yes. Both represent a method that takes one value and returns bool. They exist as separate delegate types because different APIs use different conventions.
Can I replace custom delegates with , , or ?
Mini Project
Description
Build a small console example that processes a list of products using all three delegate types. This demonstrates a realistic pattern: filter items, transform data, and then perform an action with the result.
Goal
Create a C# program that filters in-stock products, converts their names to display text, and prints the results.
Requirements
- Create a
Productclass withName,Price, andInStockproperties. - Store several products in a
List<Product>. - Use a
Predicate<Product>to keep only products that are in stock. - Use a
Func<Product, string>to convert each product into a display string. - Use an
Action<string>to print each display string.
Keep learning
Related questions
AddTransient vs AddScoped vs AddSingleton in ASP.NET Core Dependency Injection
Learn the differences between AddTransient, AddScoped, and AddSingleton in ASP.NET Core DI with examples and practical usage.
Best Way to Repeat a Character in C#: Building Repeated Strings Efficiently
Learn the best way to repeat a character in C#, compare StringBuilder, string concatenation, and simpler built-in options.
C# Array Initialization Syntaxes Explained
Learn all common C# array initialization syntaxes with examples, rules, comparisons, and mistakes beginners often make.