I try to compile the following code in C#:
public static T FirstEffective(IEnumerable<T> list)
{
Predicate<T> pred = x => x != null;
return Enumerable.FirstOrDefault(list, pred);
}
The compiler (Mono/.NET 4.0) gives the following error:
File.cs(139,47) The best overloaded method match for `System.Linq.Enumerable.FirstOrDefault<T>(this System.Collections.Generic.IEnumerable<T>,System.Func<T,bool>)' has some invalid arguments
/usr/lib/mono/4.0/System.Core.dll (Location of the symbol related to previous error)
File.cs(139,47): error CS1503: Argument `#2' cannot convert `System.Predicate<T>' expression to type `System.Func<T,bool>'
This is rather strange since a Predicate<T>
is in fact a function that takes as input a parameter T
and returns a bool
(T
is even "covariant" thus a specialization of T
is allowed). Do delegates do not take the "Liskov Substitution principle" into account to derive that Predicate<T>
is equivalent to Func<T,bool>
? As far as I know this equivalence problem should be decidable.
Delegate types are not implicitly convertible, even when they have all the same parameter and return information. There is an easy workaround for your case though. You can use the
.Invoke
method on your delegate instance.As to the question of why delegates work this way, the answer is that it was a design decision. Classes that have identical public interfaces aren't implicitly convertible either, so it's not really inconsistent.
C# specification is clear about that:
That's why your code doesn't compile.
You can make it work by calling the delegate, instead of passing it:
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.
Quite belated but coincidentally I stumbled up on the same question and the accurate answer can be found here: important comment
Basically it means that it's an inconsistency based on an unfortunate decision to implement it this way. Whilst
predicate<T> == func<T, bool>
, they are different types despite the same signature. I suppose for reasons of backward compatibility one can convert an expression and/or lambda and then return a predicate throughnew predicate<T>(func<T, bool>)
.