本文仅作为参考大佬们文章的总结。
Lambda表达式是C#中一种强大的语法特性,它极大地简化了匿名方法的编写,使代码更加简洁和富有表现力。
Lambda表达式是C#中一种简洁的表示匿名函数的方法,它使用=>
运算符(称为lambda运算符)将参数列表与表达式或语句块分隔开。Lambda表达式主要用于LINQ查询、事件处理程序、回调函数等场景,使得代码更加简洁和易于阅读。
Lambda表达式的基本语法形式如下:
(input-parameters) => expression-or-statement-block
其中:
input-parameters
:参数列表,可以为空或包含多个参数
=>
:lambda运算符,分隔参数列表和方法体
expression-or-statement-block
:可以是一个表达式(当Lambda返回值时)或者是一个语句块(当Lambda是一个复杂方法时)
Lambda表达式和匿名方法都是用来表示没有名称的方法,但Lambda表达式具有更简洁的语法和更强的灵活性。
匿名方法示例:
Func add = delegate(int x, int y) { return x + y; };
Console.WriteLine(add(3, 4)); // 输出7
Lambda表达式示例:
Func add = (x, y) => x + y;
Console.WriteLine(add(3, 4)); // 输出7
如上所示,Lambda表达式更加简洁,尤其在处理简单的逻辑时,能够大大减少代码的冗余。
如果Lambda表达式不需要参数,可以使用空括号()
表示:
Action sayHello = () => Console.WriteLine("Hello, World!");
sayHello(); // 输出"Hello, World!"
不返回值的委托类型(即返回类型是void
)。
Lambda表达式() => Console.WriteLine("Hello, World!")
相当于一个没有参数、执行Console.WriteLine("Hello, World!")
的方法。
如果只有一个参数,可以省略括号:
Func square = x => x * x;
int result = square(5); // result = 25
Console.WriteLine(result); // 输出25
多个参数需要用逗号分隔并放在括号内:
Func isSumEven = (x, y) => (x + y) % 2 == 0;
bool even = isSumEven(3, 5); // even = True
Console.WriteLine(even); // 输出True
根据Lambda表达式主体的复杂度,可以分为两种形式:
如果Lambda表达式只包含一个表达式,可以使用表达式Lambda:
// 定义一个接收两个整数并返回它们之和的Lambda表达式
Func add = (x, y) => x + y;
int result = add(3, 5);
Console.WriteLine(result); // 输出8
如果Lambda表达式包含多个语句,可以使用语句Lambda:
// 定义一个接收一个整数并打印其平方的Lambda表达式
Action printSquare = (x) =>
{
int square = x * x;
Console.WriteLine($"The square of {x} is {square}");
};
printSquare(4); // 输出"The square of 4 is 16"
Lambda表达式能够访问其所在作用域中的外部变量,这一特性称为"闭包"。
Lambda表达式在执行时会创建一个闭包,捕获并保留外部变量的引用。
int factor = 2;
Func multiply = x => x * factor;
Console.WriteLine(multiply(5)); // 输出10
factor = 3; // 修改外部变量
Console.WriteLine(multiply(5)); // 输出15
在这个例子中,Lambda表达式x => x * factor
捕获了外部变量factor
,并且会使用该变量在执行时的最新值。
在Lambda表达式中,C#编译器通常可以自动推断参数的类型,因此不必明确指定参数类型,除非需要明确指定。
Func add = (a, b) => a + b; // 类型推断
编译器推断a
和b
为int
类型,因为Func
指定了参数类型。如果需要明确指定类型,可以写成:
Func add = (int a, int b) => a + b;
Lambda表达式通常用来创建委托或表达式树。委托是一种类型安全的函数指针,用于引用方法。Lambda表达式可以直接赋值给委托。
// 定义一个委托类型
delegate int Operation(int x, int y);
// 使用Lambda表达式来创建委托实例
Operation multiply = (x, y) => x * y;
int product = multiply(3, 4); // product = 12
Console.WriteLine(product);
Lambda表达式在LINQ查询中扮演着非常重要的角色。在LINQ中,我们使用Lambda表达式来指定查询的条件、排序规则、投影等。
List numbers = new List { 1, 5, 12, 18, 7, 2 };
var result = numbers.Where(x => x > 10).ToList();
foreach (var number in result)
{
Console.WriteLine(number); // 输出12, 18
}
在这段代码中,Where
方法接受了一个Lambda表达式x => x > 10
,它表示过滤出所有大于10的数字。
Lambda表达式也可以用于数据转换,比如对每个元素进行平方操作:
List numbers = new List { 1, 5, 12, 18, 7, 2 };
var result = numbers.Select(x => x * x).ToList();
foreach (var number in result)
{
Console.WriteLine(number); // 输出1, 25, 144, 324, 49, 4
}
Lambda表达式还可以用于排序和分组操作:
var sortedNumbers = numbers.OrderBy(x => x).ToList();
var groupedNumbers = numbers.GroupBy(x => x % 2 == 0 ? "Even" : "Odd").ToList();
Lambda表达式在事件处理中也得到了广泛应用。例如,给按钮点击事件添加处理器:
button.Click += (sender, e) => { Console.WriteLine("Button clicked!"); };
这种方式使得代码更加简洁,不需要额外定义事件处理方法1。
Lambda表达式常用于集合的各种操作,如ForEach
、Find
、RemoveAll
等:
List names = new List { "Alice", "Bob", "Charlie" };
names.ForEach(name => Console.WriteLine(name)); // 输出所有名字
// 查找特定条件的元素
string result = names.Find(name => name.Length > 4); // "Charlie"
C#中的=>
符号不仅用于Lambda表达式,还用于表达式主体定义(Expression-bodied members),这是两种不同的语法特性。
表达式主体定义是C# 6.0引入的语法糖,用于简化属性、方法等的定义:
// 传统属性定义
public CurrentUser CurrentUser
{
get { return new CurrentUser(3); }
}
// 表达式主体定义
public CurrentUser CurrentUser => new CurrentUser(3);
// 传统方法定义
public int Add(int a, int b)
{
return a + b;
}
// 表达式主体方法
public int Add(int a, int b) => a + b;
表达式主体定义有一些限制:
不能包含控制流语句(如if
、switch
、for
、while
等)
不能是void
返回类型(对于方法)
主要用于简单的单行表达式实现
简单操作:当需要简单的数据转换、筛选或操作时
LINQ查询:在LINQ查询中定义条件、投影或排序规则
事件处理:为事件添加简单的处理逻辑
回调函数:需要传递简单函数作为参数时
复杂逻辑:当函数体过于复杂时,考虑使用命名方法
需要重用的代码:如果逻辑需要在多个地方使用,定义命名方法更合适
调试困难:过于复杂的Lambda表达式可能难以调试
Lambda表达式通常比匿名方法更快,因为它们不需要额外的委托实例化步骤
但频繁创建Lambda表达式可能会导致内存压力,特别是在循环中
对于性能敏感的代码,可以考虑缓存委托实例
保持Lambda表达式简短
对于复杂逻辑,考虑使用语句Lambda或提取为命名方法
为参数使用有意义的名称,即使类型可以推断
C#中的Lambda表达式是一种强大而灵活的工具,它通过简洁的语法实现了匿名函数的定义。主要特点包括:
简洁语法:使用=>
运算符,比匿名方法更简洁
灵活性:支持从简单表达式到复杂语句块的各种形式
闭包支持:可以捕获和使用外部变量
类型推断:在大多数情况下不需要显式声明参数类型
广泛应用:特别适合LINQ查询、事件处理和集合操作