Action doesn't return anything,
Func does.
Predicate takes one parameter and returns a boolean.
Table of contents
Action<T1, T2, T3, ...>
Actionhas no return value.- The types
T1,T2,T3and so on specify the parameters' types. - There can be between 0 and 16 parameters:
ActionAction<T1>Action<T1, T2>Action<T1, T2, T3>- ...
Action<T1, T2, T3, ..., T16>
Examples:
Actiontakes no parameters and returns nothing.Action<int>takes oneintparameter and returns nothing.Action<int, bool, int>takes three parameters of typesint,boolandint, 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>
Funcreturns a value of typeTResult.- The types
T1,T2,T3and 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>
TResultis 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 astring.Func<int, string>takes oneintparameter and returns astring.Func<int, bool, int, string>takes three parameters of typesint,boolandint, in that order, and returns astring.
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>
Predicatereturns a boolean.Predicatetakes one parameter of typeT.
Examples:
Predicate<int>takes oneintparameter and returns a boolean.Predicate<string>takes onestringparameter 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:
Funchas overloads that take more than one input type, so it's more flexible thanPredicate.Func<T, bool>is clear (given that you know howFuncs work), whereasPredicateis 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: