6.3 匿名方法与Lambda表达式
概述
匿名方法和Lambda表达式是C#中简化委托使用的两种重要语法特性。它们允许开发者以更简洁的方式定义内联方法,无需显式声明具名方法,特别适用于事件处理和LINQ查询等场景。
匿名方法
基本语法
delegate(parameters) {
// 方法体
};
特点
- 通过
delegate关键字声明 - 可省略参数列表(当委托类型明确时)
- 必须包含方法体
- 可以访问外部变量(形成闭包)
示例
// 传统委托
Button.Click += new EventHandler(Button_Click);
void Button_Click(object sender, EventArgs e) {
MessageBox.Show("Clicked!");
}
// 匿名方法
Button.Click += delegate(object sender, EventArgs e) {
MessageBox.Show("Clicked!");
};
Lambda表达式
进化历程
匿名方法 → Lambda表达式 → 表达式Lambda
语法形式
- 完整形式:
(input-parameters) => { statements; } - 表达式形式:
(input-parameters) => expression
特点
- 使用
=>运算符(读作"goes to") - 参数类型可推断时可省略类型声明
- 单参数时可省略括号
- 方法体为单条语句时可省略大括号
示例
// 完整Lambda
Button.Click += (object sender, EventArgs e) => {
MessageBox.Show("Clicked!");
};
// 简化Lambda
Button.Click += (sender, e) => MessageBox.Show("Clicked!");
// LINQ中的Lambda
var result = numbers.Where(x => x > 5).OrderBy(x => x);
对比与选择
| 特性 | 匿名方法 | Lambda表达式 |
|---|---|---|
| 语法复杂度 | 中等 | 简洁 |
| 类型推断 | 有限支持 | 完全支持 |
| 表达式体 | 不支持 | 支持 |
| 弃元参数(_) | 不支持 | C# 9.0+支持 |
| 适用场景 | 需要兼容旧版C#(2.0)时使用 | 现代C#代码首选 |
高级用法
闭包现象
int factor = 2;
Func<int, int> multiplier = x => x * factor;
factor = 10;
Console.WriteLine(multiplier(5)); // 输出50而非10
表达式树
Expression<Func<int, bool>> expr = x => x > 5;
var compiled = expr.Compile();
Console.WriteLine(compiled(10)); // 输出True
注意事项
- 避免在循环中创建Lambda表达式(可能导致意外闭包)
- 注意多线程环境下的变量捕获
- 复杂的Lambda表达式应考虑重构为具名方法
- 调试时Lambda表达式会显示为
<>c__DisplayClass#
最佳实践
- 优先使用Lambda表达式而非匿名方法
- 保持Lambda表达式简短(不超过3-5行)
- 对复杂逻辑使用具名方法
- 注意代码可读性,必要时添加注释
练习题
将以下匿名方法转换为Lambda表达式:
delegate(int x) { return x * x; }编写一个Lambda表达式,过滤出字符串列表中长度大于5的元素
解释以下代码的输出结果:
var actions = new List<Action>(); for (int i = 0; i < 3; i++) { actions.Add(() => Console.WriteLine(i)); } foreach (var action in actions) { action(); }
