Why a `Predicate<T>` doesn't match a `Func<T,bool>`?

旧巷老猫 提交于 2019-12-01 15:08:22
MarcinJuraszek

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.

recursive

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.

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

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.

Valmont

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 through new predicate<T>(func<T, bool>).

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!