Lambda 在 FindAll 中有效,但在将其用作 Func(或表达式)时无效
Lambda works in FindAll, but not when using it as an Func (or Expression)
以下代码无法编译:
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() 关键字使其与谓词一起工作,但这不是这里的问题。
编辑:为什么会有人对此投反对票?这个问题一点也不糟糕,因为问题域确实不是逻辑性质的。真人啊
FindAll 需要一个 Predicate
而不是方法定义 Array.FindAll<T> Method (T[], Predicate<T>)
中看到的 Function
当您尝试传递 theLambda
时,它试图传递一个函数,而该方法需要一个谓词。您可以尝试将 theLambda 定义为
Predicate<Person> theLambda = (p) => p.Year >= 1992;
谓词是一个 returns 布尔值的函数,它是 FindAll 方法过滤结果所需要的。
根据答案 here,您可以执行以下操作。
foreach (Person pers in PersonList.FindAll(new Predicate<Person>(theLambda)))
之所以有效,是因为如果您将 lambda 声明为内联,编译器会隐式为其分配正确的类型,即 Predicate<Person>
。您不必明确告诉编译器 lambda 类型,因为它已经知道它应该采用 Person
和 return 如果您在 List<Person>
.
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:
When writing lambdas, you often do not have to specify a type for the
input parameters because the compiler can infer the type based on the
lambda body, the parameter’s delegate type, and other factors as
described in the C# Language Specification. For most of the standard
query operators, the first input is the type of the elements in the
source sequence. So if you are querying an IEnumerable<Customer>
, then
the input variable is inferred to be a Customer
object
令人困惑的部分是 Predicate
在逻辑上是一个 Func
,它采用某种类型的对象 T
而 return 是一个 bool
,但是由于某种原因,这种输入不起作用,您必须使用 Predicate<T>
。内联声明 lambda 函数避免了这种混淆,因为您只需编写 lambda 主体并让编译器自行推断类型。
以下代码无法编译:
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() 关键字使其与谓词一起工作,但这不是这里的问题。
编辑:为什么会有人对此投反对票?这个问题一点也不糟糕,因为问题域确实不是逻辑性质的。真人啊
FindAll 需要一个 Predicate
而不是方法定义 Array.FindAll<T> Method (T[], Predicate<T>)
Function
当您尝试传递 theLambda
时,它试图传递一个函数,而该方法需要一个谓词。您可以尝试将 theLambda 定义为
Predicate<Person> theLambda = (p) => p.Year >= 1992;
谓词是一个 returns 布尔值的函数,它是 FindAll 方法过滤结果所需要的。
根据答案 here,您可以执行以下操作。
foreach (Person pers in PersonList.FindAll(new Predicate<Person>(theLambda)))
之所以有效,是因为如果您将 lambda 声明为内联,编译器会隐式为其分配正确的类型,即 Predicate<Person>
。您不必明确告诉编译器 lambda 类型,因为它已经知道它应该采用 Person
和 return 如果您在 List<Person>
.
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:
When writing lambdas, you often do not have to specify a type for the input parameters because the compiler can infer the type based on the lambda body, the parameter’s delegate type, and other factors as described in the C# Language Specification. For most of the standard query operators, the first input is the type of the elements in the source sequence. So if you are querying an
IEnumerable<Customer>
, then the input variable is inferred to be aCustomer
object
令人困惑的部分是 Predicate
在逻辑上是一个 Func
,它采用某种类型的对象 T
而 return 是一个 bool
,但是由于某种原因,这种输入不起作用,您必须使用 Predicate<T>
。内联声明 lambda 函数避免了这种混淆,因为您只需编写 lambda 主体并让编译器自行推断类型。