当前位置: 首页 > 编程语言 > C#

为什么`Predicate`不匹配`Func`?分享

时间:2023-04-10 19:14:56 C#

为什么`Predicate`不匹配`Func`?我尝试在C#中编译以下代码:publicstaticTFirstEffective(IEnumerablelist){Predicatepred=x=>x!=null;返回Enumerable.FirstOrDefault(list,pred);编译器(Mono/.NET4.0)给出以下错误:File.cs(139,47)Thebestoverloadedmethodmatchfor`System.Linq.Enumerable.FirstOrDefault(thisSystem.Collections.Generic.IEnumerable,System.Func)'有一些无效参数/usr/lib/mono/4.0/System.Core.dll(与先前错误相关的符号位置)File.cs(139,47):错误CS1503:参数“#2”无法转换“系统”.Predicate'表达式键入`System.Func'相当奇怪,因为Predicate实际上是一个函数,它将参数T作为输入并返回bool(T甚至是“协变的”,因此允许T的特化)。委托人难道不考虑“里氏代换原则”就推导出Predicate等价于Func吗?据我所知,这个等价问题应该是可判定的。C#规范很明确:15.1代表声明C#中的委托类型是名称等效的,而不是结构等效的。具体来说,具有相同参数列表和返回类型的两个不同的委托类型被认为是不同的委托类型。这就是您的代码无法编译的原因。您可以通过调用委托而不是传递它来完成这项工作:publicstaticTFirstEffective(IEnumerablelist){Predicatepred=x=>x!=null;返回Enumerable.FirstOrDefault(list,x=>pred(x));更新EricLippert写了一篇很棒的博客文章:前微软C#团队成员,详细回答了您的问题:委托和结构标识。委托类型不可隐式转换,即使它们具有所有相同的参数和返回信息。但是,您的情况有一个简单的解决方法。您可以在委托实例上使用.Invoke方法。publicstaticTFirstEffective(IEnumerablelist){谓词pred=x=>x!=null;返回Enumerable.FirstOrDefault(列表,pred.Invoke);}至于委托为什么这样工作的问题,答案是这是一个设计决定。具有相同公共接口的类也不可隐式转换,因此并不是真正的不一致。很晚了,但巧合的是我偶然发现了同样的问题,可以在这里找到确切的答案:重要评论基本上这意味着它是基于一个不幸的决定,以这种方式不一致地实施它。虽然predicate==func,但它们是不同的类型,尽管具有相同的签名。我认为出于向后兼容性的原因,可以转换表达式和/或lambda,然后通过新谓词(func)返回谓词。以上是C#学习教程:为什么`Predicate`不匹配`Func`?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: