C# 匿名方法与 Lambda 表达式全解析

在日常 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
相关推荐
半亩码田1 天前
C#转Python第3.1篇:Python 的 class 没有访问修饰符?面向对象的另一条路
开发语言·python·c#
唐青枫1 天前
别再手写 args[0]:C#.NET CommandLineParser 命令行工具实战详解
c#·.net
LccKyI1 天前
C#学习day06(方法/函数及其关键字,附思维导图)
经验分享·学习·c#
.Peter1 天前
.NET/WPF 程序在部分 Windows 电脑无法保存用户环境变量:使用 DPAPI 实现安全兼容
windows·信息安全·c#·.net·wpf·环境变量·dpapi
农村小镇哥1 天前
怎么把HTM格式转化成WORD
ui·c#·word
农村小镇哥1 天前
C#读取CSV文件的方法
服务器·数据库·c#
FuckPatience1 天前
C# 报错参数无效
c#
北域码匠2 天前
PID 控制算法完整详解(C# 原生实现,无第三方库)
c#·pid控制·工控开发·闭环控制·自动控制算法·数字pid·增量式pid
离陌在学C#2 天前
C# 重载与重写:深入理解面向对象编程的核心概念
java·c#
asdzx672 天前
Java 实战:基于 Spire.Doc 高效提取 Word 文档文本与图片
java·c#·word