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
相关推荐
格林威2 小时前
工业相机图像高速存储(C#版):直接IO(Direct I/O)绕过系统缓存,附堡盟相机实战代码!
开发语言·人工智能·数码相机·计算机视觉·缓存·c#·视觉检测
格林威3 小时前
工业相机图像高速存储(C#版):直接IO(Direct I/O)方法,附Basler相机实战代码!
开发语言·人工智能·数码相机·计算机视觉·c#·视觉检测·工业相机
顾温3 小时前
c# 多线程
开发语言·c#
格林威3 小时前
工业相机图像高速存储(C#版):直接IO存储方法,附海康相机C#实战代码!
开发语言·人工智能·数码相机·c#·工业相机·海康相机·堡盟相机
csdn_aspnet3 小时前
使用 Ollama,通过 C#、语义内核和 Google Gemma 3 构建本地 AI 代理
人工智能·ai·c#·ollama·gemma
唐青枫3 小时前
C#.NET ReadOnlySequence 深入解析:多段内存遍历与零拷贝协议解析
c#·.net
废嘉在线抓狂.4 小时前
TimeLine如何自定义轨道
unity·c#·对话系统
hixiong12313 小时前
C# OpenvinoSharp使用RAD进行缺陷检测
开发语言·人工智能·c#·openvino