且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

为什么'Predicate< T>'与'Func< T,bool>'不匹配?

更新时间:2022-10-30 09:07:10

C#规范很明确:


15.1委托声明



C#中的委托类型与名称等同,结构上相同。
具体而言,具有相同
参数列表和返回类型的两种不同委托类型被视为不同委托
类型。
blockquote>

这就是为什么你的代码不能编译。



你可以通过调用委托而不是传递它:

  public static T FirstEffective(IEnumerable< T> list){
Predicate< T> pred = x => x!= null;
返回Enumerable.FirstOrDefault(list,x => pred(x));
}

更新
$ b

Eric Lippert写了一篇很棒的博客文章:C#团队的前任成员是微软,他非常详细地回答您的问题:代表和结构特征

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.

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.