Lambda在FindAll中有效,但在将其用作Func(或表达式)时无效

本文关键字:Func 表达式 无效 有效 FindAll Lambda | 更新日期: 2023-09-27 18:20:12

下面的代码无法编译:

Func<Person, bool> theLambda = (p) => p.Year >= 1992;
foreach (Person pers in PersonList.FindAll(theLambda))
{
    Console.WriteLine(pers.Name);
}
public class Person
{
    public string Name { get; set; }
    public int Year { get; set; }
    public Person(string Name, int Year )
    {
        this.Name = Name; this.Year = Year;
    }
}  

然而,如果我直接用lambda替换变量"theLambda",那么它就可以正常工作了。这是怎么回事?(温柔一点,我是个新手)。提前感谢您
(1) 我读了错误消息,但对我来说没有任何意义。
(2) 是的,我可以通过使用compile()关键字使它与谓词一起工作,但这不是问题所在。

编辑:为什么会有人投反对票?这个问题一点也不坏,因为问题域实际上不是逻辑性质的。真正的人

Lambda在FindAll中有效,但在将其用作Func(或表达式)时无效

它之所以有效,是因为如果在内联中声明lambda,编译器会隐式为其指定正确的类型,即Predicate<Person>。您不必显式地告诉编译器lambda类型,因为它已经知道,如果您在List<Person>上调用FindAll,它应该接受Person并返回bool

foreach (Person pers in PersonList.FindAll(p => p.Year >= 1992))
{
    Console.WriteLine(pers.Name);
}

您也可以使用具有相同功能的Enumerable.Where-LINQ方法使其可读性更强:

foreach (Person pers in PersonList.Where(p => p.Year >= 1992))
{
    Console.WriteLine(pers.Name);
}

来自msdn:

在编写lambda时,通常不必为输入参数,因为编译器可以根据lambda主体、参数的委托类型和其他因素如C#语言规范中所述。对于大多数标准查询运算符,第一个输入是源序列。因此,如果您正在查询IEnumerable<Customer>,那么输入变量被推断为Customer对象

令人困惑的是,Predicate在逻辑上是Func,它接受某种类型的T对象并返回bool,但由于某些原因,这种类型不起作用,您必须使用Predicate<T>。内联声明lambda函数可以避免这种混淆,因为您只需编写lambda主体并让编译器自己推断类型。

FindAll需要Predicate,而不是方法定义Array.FindAll<T> Method (T[], Predicate<T>) 中的Function

当您尝试传递theLambda时,它就是在尝试传递一个Function,而该方法需要一个Predicate。您可以尝试将Lambda定义为

Predicate<Person> theLambda = (p) => p.Year >= 1992;

谓词是一个返回布尔值的函数,这是FindAll方法过滤结果所需要的。

根据这里的答案,您可以执行以下操作。

foreach (Person pers in PersonList.FindAll(new Predicate<Person>(theLambda)))