c# Lambda 表达式

在 C# 中,Lambda 表达式是一种简洁的语法,用于创建匿名函数。它可以作为参数传递给方法,或用于定义委托类型的变量。Lambda 表达式在 LINQ 查询、事件处理和异步编程中广泛使用。

1. 基本语法

Lambda 表达式使用 =>(称为 Lambda 运算符)分隔参数和表达式主体。

无参数
复制代码
() => Console.WriteLine("Hello, Lambda!");
单个参数
复制代码
x => x * x;  // 等价于:int Square(int x) { return x * x; }
多个参数
复制代码
(x, y) => x + y;  // 加法运算
显式参数类型
复制代码
(int x, int y) => x * y;  // 乘法运算

2. Lambda 表达式的主体

表达式体

如果 Lambda 只包含一个表达式,可以省略 return 语句。

复制代码
x => x.Length;  // 返回字符串长度
语句体

如果 Lambda 包含多个语句,需要用大括号 {} 包裹,并显式使用 return

复制代码
x => {
    Console.WriteLine($"Processing: {x}");
    return x * x;
};

3. 捕获外部变量

Lambda 可以捕获其定义所在作用域中的变量。

复制代码
int multiplier = 10;
Func<int, int> multiply = x => x * multiplier;  // 捕获 multiplier 变量
​
Console.WriteLine(multiply(5));  // 输出 50

4. 在 LINQ 查询中的应用

Lambda 表达式是 LINQ 的核心,用于筛选、投影和排序数据。

筛选数据(Where)
复制代码
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
var evenNumbers = numbers.Where(n => n % 2 == 0);  // [2, 4]
投影数据(Select)
复制代码
var squared = numbers.Select(n => n * n);  // [1, 4, 9, 16, 25]
排序(OrderBy)
复制代码
var sorted = numbers.OrderBy(n => n);  // 升序排序

5. 作为委托类型使用

Lambda 表达式可以赋值给委托类型的变量。

使用 Func<> 委托
复制代码
Func<int, int, int> add = (x, y) => x + y;
int result = add(3, 5);  // 结果:8
使用 Action<> 委托(无返回值)
复制代码
Action<string> print = message => Console.WriteLine(message);
print("Hello, Lambda!");

6. 异步 Lambda

使用 async 关键字创建异步 Lambda 表达式。

复制代码
Func<Task<int>> asyncLambda = async () => {
    await Task.Delay(1000);
    return 42;
};
​
await asyncLambda();  // 异步执行

7. 与表达式树结合

Lambda 表达式可以转换为表达式树(Expression<Func<>>),用于动态查询。

复制代码
Expression<Func<int, bool>> expression = n => n > 5;
// 表达式树可以被编译或分析

8. 示例:组合使用 Lambda

复制代码
List<Person> people = new List<Person> {
    new Person { Name = "Alice", Age = 30 },
    new Person { Name = "Bob", Age = 25 },
    new Person { Name = "Charlie", Age = 35 }
};
​
// 查询年龄大于30的人,并按姓名排序
var result = people
    .Where(p => p.Age > 30)
    .OrderBy(p => p.Name)
    .Select(p => p.Name);
​
// 结果:["Charlie"]

Lambda 与匿名方法的区别

Lambda 表达式是匿名方法的语法糖,更简洁且支持表达式树。例如:

复制代码
// 匿名方法
delegate(int x) { return x * x; }
​
// Lambda 表达式(更简洁)
x => x * x

注意事项

  • 捕获变量的生命周期:Lambda 捕获的变量在 Lambda 执行时才求值,可能导致意外结果。

  • 性能:表达式树的编译开销较大,避免在高性能场景中频繁使用。

  • 类型推断:编译器会自动推断 Lambda 参数的类型,但在复杂场景中可能需要显式指定。

Lambda 表达式是 C# 中强大且灵活的特性,能够显著简化代码并提高可读性。