LINQ Lambda 表达式

C#3.0(.NET 3.5)引入了lambda表达式以及 LINQ。lambda表达式是使用某些特殊语法表示匿名方法的一种较短方法。

例如,采用以下匿名方法检查学生是否为青少年:

delegate(Student s) { return s.Age > 12 && s.Age < 20; };
Dim isStudentTeenAger = Function(s As Student) As Boolean
                                    Return s.Age > 12 And s.Age < 20
                        End Function

可以使用C#和VB.Net中的Lambda表达式来表示上述匿名方法,如下所示:

s => s.Age > 12 && s.Age < 20
Function(s) s.Age  > 12 And s.Age < 20

让我们看看lambda表达式是如何从以下匿名方法演变而来的。

delegate(Student s) { return s.Age > 12 && s.Age < 20; };

Lambda表达式是通过首先删除委托关键字和参数类型并添加lambda运算符=>从匿名方法演变而来的。

来自匿名方法的Lambda表达式

上面的lambda表达式绝对有效,但是如果我们只有一个返回值的语句,则不需要花括号,return和分号。因此我们可以删除它。

另外,如果只有一个参数,则可以删除括号()。

来自匿名方法的Lambda表达式

因此,我们得到了lambda表达式:s => s.Age > 12 && s.Age < 20 其中s是参数,=>是lambda运算符,s.Age > 12 && s.Age < 20是表达式主体:

C#中的Lambda表达式结构

我们在VB.Net中获得lambda表达式的方式可以如下编写:

VB.Net中的Lambda表达式结构

lambda表达式的调用方式与使用()的委托调用方式相同。

注意:VB.Net不支持lambda运算符=>

具有多个参数的Lambda表达式

如果您需要传递多个参数,则可以将参数括在括号中,如下所示:

    示例:在Lambda表达式C#中指定多个参数

(s, youngAge) => s.Age >= youngage;

如果觉得参数表达不清,您还可以给出每个参数的类型:

(Student s,int youngAge) => s.Age >= youngage;
示例:在Lambda表达式中指定多个参数VB.Net
Function(s, youngAge) s.Age >= youngAge

不带参数的Lambda表达式

lambda表达式中不必至少有一个参数。lambda表达式也可以不带任何参数来指定。

() => Console.WriteLine("无参数 lambda 表达式")

Lambda表达主体中的多个语句

如果要在主体中包含多个语句,可以将表达式用大括号括起来:

(s, youngAge) =>{
  Console.WriteLine("在主体中包含多个语句的Lambda表达式");
    
  Return s.Age >= youngAge;}
Function(s , youngAge)
    
    Console.WriteLine("在主体中包含多个语句的Lambda表达式")
    
    Return s.Age >= youngAge

End Function

在Lambda表达主体中声明局部变量

您可以在表达式主体中声明一个变量,以在表达式主体中的任何地方使用它,如下所示:

s =>
{   int youngAge = 18;

    Console.WriteLine("在主体中包含多个语句的Lambda表达式");

    return s.Age >= youngAge;
}
Function(s) 
                                      
        Dim youngAge As Integer = 18
            
        Console.WriteLine("在主体中包含多个语句的Lambda表达式")
            
        Return s.Age >= youngAge
            
End Function

Lambda表达式也可以分配给内置委托,例如Func,Action和Predicate。

将Lambda表达式分配给委托

可以将lambda表达式分配给Func<in T, out TResult>委托类型。Func委托中的最后一个参数类型是返回类型,其余参数是输入参数。访问C#教程的Func委托部分以了解更多信息。

考虑以下lambda表达式,以了解学生是否是青少年。

Func<Student, bool> isStudentTeenAger = s => s.age > 12 && s.age < 20;

Student std = new Student() { age = 21 };

bool isTeen = isStudentTeenAger(std);// 返回false
Dim isStudentTeenAger As Func(Of Student, Boolean) = Function(s) s.Age > 12 And s.Age < 20

Dim stud As New Student With {.Age = 21}

Dim isTeen As Boolean = isStudentTeenAger(stud) // 返回 false

在上面的示例中,Func委托期望第一个输入参数为Student类型,而返回类型为布尔值。lambda表达式 s => s.age > 12 && s.age < 20满足Func <Student,bool>委托要求,如下所示:

具有Lambda 表达式的Func委托

上面显示的Func <>委托将变成一个如下所示的函数。

bool isStudentTeenAger(Student s)
{
    return s.Age > 12 && s.Age < 20;
}

Action 委托

与Func委托不同,Action委托只能具有输入参数。当您不需要从lambda表达式返回任何值时,请使用Action委托类型。

Action<Student> PrintStudentDetail = s => Console.WriteLine("Name: {0}, Age: {1} ", s.StudentName, s.Age);

Student std = new Student(){ StudentName = "Bill", Age=21};

PrintStudentDetail(std);//输出: Name: Bill, Age: 21
Dim printStudentDetail As Action(Of Student) = Sub(s) Console.WriteLine("Name: {0}, Age: {1} ", s.StudentName, s.Age)
    
Dim stud As New Student With {.StudentName = "Bill", .Age = 21}
        
printStudentDetail(stud)//输出: Name: Bill, Age: 21

LINQ查询中的Lambda表达式

通常,lambda表达式与LINQ查询一起使用。可枚举的静态类包括其中的扩展方法IEnumerable<T>wheres接受Func<TSource,bool>。因此,收集的Where()扩展方法IEnumerable<Student>需要通过Func<Student,bool>,如下所示:

Where扩展方法中的Func委托参数

因此,现在,您可以使用Where()如下所示的方法语法将分配给Func委托的lambda表达式传递给扩展方法:

IList<Student> studentList = new List<Student>(){...};

Func<Student, bool> isStudentTeenAger = s => s.age > 12 && s.age < 20;

var teenStudents = studentList.Where(isStudentTeenAger).ToList<Student>();
IList<Student> studentList = new List<Student>(){...};

Func<Student, bool> isStudentTeenAger = s => s.age > 12 && s.age < 20;

var teenStudents = from s in studentList
                   where isStudentTeenAger(s)
                   select s;

您可以在VB.Net中遵循相同的方法来传递Func委托。

要记住的要点

  1. Lambda表达式是表示匿名方法的简写方法。

  2. Lambda表达式语法: 参数 => 表达式主体

  3. Lambda表达式可以具有零参数。

  4. Lambda表达式的括号()中可以有多个参数。

  5. Lambda表达式可以在大括号{}中的主体表达式中包含多个语句。

  6. Lambda表达式可以分配给Func,Action或Predicate委托。

  7. 可以以类似于委托的方式调用Lambda Expression。