Why FuncT,bool instead of PredicateT?
While Predicate
has been introduced at the same time that List<T>
and Array<T>
, in .net 2.0, the different Func
and Action
variants come from .net 3.5.
So those Func
predicates are used mainly for consistency in the LINQ operators. As of .net 3.5, about using Func<T>
and Action<T>
the guideline states:
Do use the new LINQ types
Func<>
andExpression<>
instead of custom
delegates and predicates
Why a `PredicateT` doesn't match a `FuncT,bool`?
C# specification is clear about that:
15.1 Delegate declarations
Delegate types in C# are name equivalent, not structurally equivalent.
Specifically, two different delegate types that have the same
parameter lists and return type are considered different delegate
types.
That's why your code doesn't compile.
You can make it work by calling the delegate, instead of passing it:
public static T FirstEffective (IEnumerable<T> list) {
Predicate<T> pred = x => x != null;
return Enumerable.FirstOrDefault (list, x => pred(x));
}
Update
There is a great blog post by Eric Lippert: former member of C# Team as Microsoft, which answers your question in much details: Delegates and structural identity.
Why is it impossible to cast FuncT, bool to PredicateT?
It is a little silly that the IEnumerable<T>.Where
extension method and List<T>
's RemoveAll
method take two different types. However, this is a simple work-around, since the local function can be used to initialize both a Func<int, bool>
and a Predicate<int>
:
var l = new List<int> {1, 2, 3, 5, 5, 6, 6};
bool Pred(int i) => i < 5;
var wh = l.Where(Pred);
var rem = l.RemoveAll(Pred);
Isn't FuncT, bool and PredicateT the same thing after compilation?
They share the same signature, but they're still different types.
Using PredicateT or a FuncT in method to filter
You can use
public IEnumerable<Claim> FindAllClaims(this IEnumerable<Claim> source, Expression<Predicate<Claim>> condition) {
return source.Where(condition)
}
or
public IEnumerable<Claim> FindAllClaims(this IEnumerable<Claim> source, Expression<Func<Claim,bool>> condition) {
return source.Where(condition)
}
Converting a PredicateT to a FuncT, bool
public bool DoAllHaveSomeProperty()
{
return m_instrumentList.All(i => m_filterExpression(i));
}
FindAll - PredicateTSource vs FuncTSource, bool
They have the same signature, but they are fundamentally different types and cannot be cast as a reference-preserving conversion. Since FindAll
wants a Predicate<T>
: use Predicate<T>
.
Would it be nice if they were castable like this? Maybe, but it would require CLR and language changes, and is unlikely to happen.
Related Topics
String Concatenation VS String Builder. Performance
Uploading Objects to Google Cloud Storage Buckets in C#
What Is a Predicate Delegate and Where Should It Be Used
Non-Static Method Requires a Target
Why/When Would It Be Appropriate to Override Tostring
Copy File on a Network Shared Drive
What Is the Fastest Way to Combine Two Xml Files into One
Programmatically Adding Images to Rtf Document
What Is the Max Limit of Data into List<String> in C#
Should You Implement Idisposable.Dispose() So That It Never Throws
Ziparchive Creates Invalid Zip File
String Interning in .Net Framework - What Are the Benefits and When to Use Interning
C#: Should Object Variables Be Assigned to Null
How to Dispose My Filestream When Implementing a File Download in ASP.NET
Force Browser to Download PDF Document Instead of Opening It