在日常 C# 开发中,我们经常遇到这样的问题:
"我想把一个方法作为参数传递给另一个方法,但不想单独创建一个命名方法。"
这个时候,匿名方法(Anonymous Methods) 和 Lambda 表达式就派上用场了。它们不仅能让代码更简洁,还能处理临时逻辑、事件回调甚至 LINQ 查询。本文将带你全面理解它们的用法、区别和最佳实践。
1️⃣ 委托与匿名方法概念
在深入之前,我们先回顾一下 委托(Delegate) 的概念:
委托是一种类型安全的函数指针,它可以引用与其签名相同的方法,通过委托对象调用方法。
匿名方法是没有名字的方法,可以直接将代码块作为委托实现,避免创建额外的命名方法。
匿名方法示例
csharp
using System;
delegate void NumberChanger(int n);
class Program
{
static void Main()
{
NumberChanger nc = delegate(int x)
{
Console.WriteLine("Anonymous Method: {0}", x);
};
nc(10); // 输出:Anonymous Method: 10
}
}
匿名方法使用
delegate关键字定义,方法体可直接访问外部变量,适合一次性、临时逻辑。
2️⃣ Lambda 表达式简介
C# 2.0 之后,引入了 Lambda 表达式,它是匿名方法的升级版,更简洁直观,并广泛应用于 LINQ 查询和委托操作。
Lambda 语法
csharp
(parameters) => expression
// 或者
(parameters) => { statements; }
Lambda 示例
csharp
using System;
delegate void NumberChanger(int n);
class Program
{
static void Main()
{
NumberChanger nc = x => Console.WriteLine($"Lambda Expression: {x}");
nc(10); // 输出:Lambda Expression: 10
}
}
优势:
- 参数类型可省略,编译器自动推断
- 支持闭包,能够访问外部变量
- 与 LINQ 结合,代码极度简洁
3️⃣ 匿名方法 vs Lambda 表达式
| 特性 | 匿名方法 | Lambda 表达式 |
|---|---|---|
| 语法 | delegate(params) { statements; } |
(params) => expression 或 (params) => { statements; } |
| 参数类型 | 可指定,也可省略 | 可省略,自动推断 |
| 简洁性 | 相对冗长 | 简洁明了 |
| LINQ 支持 | 不常用 | 广泛用于 LINQ 查询 |
| 闭包支持 | 支持 | 支持 |
| 性能 | 略慢(编译器生成内部类) | 高效(编译器优化,特别是短小 Lambda) |
总结:Lambda 表达式是匿名方法的现代替代方案,更适合函数式编程和 LINQ 场景。
4️⃣ 实战示例:事件处理与集合操作
匿名方法作为事件处理程序
csharp
Button button = new Button();
button.Click += delegate(object sender, EventArgs e)
{
Console.WriteLine("Button clicked via Anonymous Method!");
};
Lambda 表达式作为事件处理程序
csharp
Button button = new Button();
button.Click += (sender, e) => Console.WriteLine("Button clicked via Lambda!");
Lambda 结合 LINQ 过滤集合
csharp
int[] numbers = { 1, 2, 3, 4, 5, 6 };
var evenNumbers = numbers.Where(n => n % 2 == 0);
foreach (var num in evenNumbers)
{
Console.WriteLine(num); // 输出 2 4 6
}
对比可见,Lambda 使集合处理更简洁高效,匿名方法写法冗长且可读性差。
5️⃣ 闭包与 Lambda 的妙用
Lambda 支持访问外部变量:
csharp
int factor = 5;
Func<int, int> multiply = x => x * factor;
Console.WriteLine(multiply(3)); // 输出 15
这就是所谓的闭包(Closure),可以让 Lambda 捕获并使用外部变量,方便处理动态逻辑。
6️⃣ 总结与开发建议
-
匿名方法:适合旧版 C# 或简单一次性逻辑
-
Lambda 表达式:现代开发首选,语法简洁,适合 LINQ、事件、闭包
-
实际应用建议:
- 临时事件处理 → Lambda
- LINQ 查询 → Lambda
- 复杂闭包逻辑 → Lambda 或匿名方法均可
💡 面试技巧:了解匿名方法和 Lambda 的差异,能讲清闭包和委托的关系,是常考点。
参考示例:整合匿名方法与 Lambda
csharp
using System;
using System.Linq;
delegate void NumberChanger(int n);
class Program
{
static int num = 10;
static void AddNum(int p)
{
num += p;
Console.WriteLine("Named Method: {0}", num);
}
static void Main()
{
// 匿名方法
NumberChanger nc1 = delegate(int x) { Console.WriteLine("Anonymous Method: {0}", x); };
nc1(10);
// Lambda 表达式
NumberChanger nc2 = x => Console.WriteLine($"Lambda Expression: {x}");
nc2(20);
// LINQ 示例
int[] numbers = { 1, 2, 3, 4, 5 };
var squares = numbers.Select(n => n * n);
Console.WriteLine("Squares: " + string.Join(", ", squares));
// 委托调用命名方法
NumberChanger nc3 = new NumberChanger(AddNum);
nc3(5);
}
}
运行结果:
Anonymous Method: 10
Lambda Expression: 20
Squares: 1, 4, 9, 16, 25
Named Method: 15