Why FuncT,bool instead of PredicateT?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Func<T, bool> and Predicate<T> describe the same callable shape: one input, one boolean result. The reason modern C# code more often uses Func<T, bool> is not that Predicate<T> is wrong, but that the broader .NET ecosystem standardized around the Func family for LINQ, composition, and generic APIs.
So the short answer is consistency. Predicate<T> still exists and is still fine when an API explicitly asks for it, but Func<T, bool> fits more places without adapters.
The Two Delegate Types Mean Nearly the Same Thing
These declarations are logically equivalent in shape:
Both delegates answer a yes-or-no question about a value. The difference is historical and ergonomic, not semantic.
Predicate<T> is the older specialized type. It appears in APIs such as List<T>.FindAll, List<T>.Exists, and List<T>.RemoveAll.
Func<T, bool> belongs to the general delegate family:
- '
Func<T, TResult>for computed results' - '
Action<T>for no return value' - '
Func<T1, T2, TResult>for multiple inputs'
That general family ended up being a better foundation for framework design.
Why Func<T, bool> Became More Common
The biggest reason is LINQ. Methods such as Where, Any, All, FirstOrDefault, and Count all use Func<T, bool>.
Once a codebase starts using LINQ heavily, Func<T, bool> becomes the natural default because the same delegate type works across filtering, projection, and helper methods.
It Also Composes Better
A specialized delegate type is fine until requirements grow. Suppose a rule later needs another input, such as a threshold or configuration flag. Predicate<T> has no natural family around it, while Func scales cleanly.
That matters in utility code. If your APIs are built around Func, you can compose, wrap, and pass delegates around without inventing extra delegate types for each use case.
Expression<Func<T, bool>> Is Another Practical Reason
A lot of modern .NET code does not just execute predicates in memory. It inspects them. ORMs and query providers such as Entity Framework use Expression<Func<T, bool>> so they can translate the predicate into SQL or another query language.
There is no parallel mainstream ecosystem built around Expression<Predicate<T>>. That means developers already think in terms of Func when writing query-style code.
When Predicate<T> Still Makes Sense
Predicate<T> is still appropriate when:
- a framework API requires it
- you are working with
List<T>methods that already use it - you want the type name to emphasize yes-or-no intent in a small local API
Example:
That is perfectly valid C#.
Performance Is Usually Not the Reason
Developers sometimes assume one delegate type must be faster. In ordinary application code, that is not the meaningful distinction. The real choice is compatibility with the API you are calling and how well the type composes with the rest of your code.
If you ever need to bridge them, an adapter lambda is trivial:
The adapter cost is usually irrelevant compared with the clarity of matching the API surface.
Common Pitfalls
The first mistake is assuming the two types are interchangeable just because their signatures look identical. They are different delegate types, so variables are not always assignable without an adapter. Another is introducing Predicate<T> into a new abstraction when the rest of the codebase already uses Func, which adds inconsistency for little benefit. Finally, some developers chase micro-optimizations here when the real issue is simply choosing the delegate type that matches LINQ, List<T>, or expression-tree-based code.
Summary
- '
Func<T, bool>andPredicate<T>represent the same logical shape but are different types.' - '
Predicate<T>survives mainly in older list-oriented APIs.' - '
Func<T, bool>is more common because LINQ and the widerFuncfamily use it.' - '
Expression<Func<T, bool>>is another reasonFuncdominates modern .NET code.' - Use whichever type the surrounding API expects, and adapt only when necessary.

