Action
doesn't return anything,
Func
does.
Predicate
takes one parameter and returns a boolean.
Table of contents
Action<T1, T2, T3, ...>
Action
has no return value.
T1
,
T2
,
T3
and so on specify the parameters' types.
Action
Action<T1>
Action<T1, T2>
Action<T1, T2, T3>
Action<T1, T2, T3, ..., T16>
Examples:
Action
takes no parameters and returns nothing.
Action<int>
takes one
int
parameter and returns nothing.
Action<int, bool, int>
takes three parameters
of types
int
,
bool
and
int
,
in that order,
and returns nothing.
Action lambda1 = () =>
Console.WriteLine("lambda1 was called");
// No return value
Action<int> lambda2 = (int param1) =>
Console.WriteLine($"lambda2 was called with {param1}");
// No return value
Action<int, bool, int> lambda3 = (int param1, bool param2, int param3) =>
Console.WriteLine($"lambda3 was called with {param1}, {param2} and {param3}");
// No return value
Func<T1, T2, T3, ..., TResult>
Func
returns a value of type TResult
.
The types T1
, T2
, T3
and so on specify the parameters' types.
There can be between 0 and 16 parameters:
Func<TResult>
Func<T1, TResult>
Func<T1, T2, TResult>
Func<T1, T2, T3, TResult>
Func<T1, T2, T3, ..., T16, TResult>
TResult
is always in the last position,
i.e. the last type always specifies the return value's type.
Examples:
Func<string>
takes no parameters and returns a string
.
Func<int, string>
takes one int
parameter and returns a string
.
Func<int, bool, int, string>
takes three parameters
of types int
, bool
and int
,
in that order,
and returns a string
.
Func<string> lambda1 = () =>
return "lambda1 was called";
Func<int, string> lambda2 = (int param1) =>
return $"lambda2 was called with {param1}";
Func<int, bool, int, string> lambda3 = (int param1, bool param2, int param3) =>
// `null` return value is ok too
// because strings can be null
if (!param2) return null;
return $"lambda3 was called with {param1}, {param2} and {param3}";
Predicate<T>
Predicate
returns a boolean.
Predicate
takes one parameter of type T
.
Examples:
Predicate<int>
takes one int
parameter and returns a boolean.
Predicate<string>
takes one string
parameter and returns a boolean.
Predicate<int> IsPositive = (int param) =>
return param > 0;
Predicate<string> StartsWithFoo = (string param) =>
return param?.StartsWith("foo") ?? false;
Predicate<T>
vs Func<T, bool>
Predicate<T>
is effectively the same as Func<T, bool>
.
They both take a single parameter of type T
and return a boolean.
That said,
they are not assignment-compatible.
Example from the linked Stack Overflow answer by Daniel Earwicker
(slightly modified):
public static bool IsNegative(int x)
return x < 0;
static void Main(string[] args)
Predicate<int> p = IsNegative;
Func<int, bool> f = IsNegative;
p = f; // Doesn't work
f = p; // Doesn't work
Which one to use,
Predicate<T>
or Func<T, bool>
?
If you can choose,
my hunch is that Func
is better because:
Func
has overloads that take more than one input type,
so it's more flexible than Predicate
.
Func<T, bool>
is clear (given that you know how Func
s work),
whereas Predicate
is more niche
and makes sense only if you know what a "predicate" is.
On the other hand,
Predicate<T>
is short and descriptive,
so I don't have a strong opinion
which one to prefer.
Further resources
This blog post was inspired by
Scott Steffes's
YouTube video Generic Delegate Types (Action, Func, Predicate), in C#.
There's interesting discussion about the delegate keyword versus lambda syntax
in a Reddit thread around the video.
See also these pages in the .NET docs: