导读:本期聚焦于小伙伴创作的《C#怎么使用Lambda表达式?Lambda和匿名方法的写法及LINQ应用详解》,敬请观看详情。把一段委托逻辑写得又短又清楚,是很多C#初学者转向函数式写法的第一步。Lambda表达式本质是匿名方法的语法糖,编译器会将其转为委托或表达式树。相比早期delegate关键字定义的匿名方法,Lambda用=符号直接描述参数与主体,既可用于Action、Func等委托,也能在LINQ的Where、Select中构建查询。理解这两种写法差异,有助于在List筛选、排序和集合转换时写出易维护的代码。本文通过具体示例说明语法规则与常见误用。

在C#中,Lambda表达式是一种紧凑的匿名函数写法,可以用来创建委托或表达式树。它从C# 3.0开始引入,目的是简化之前只能用delegate关键字写的匿名方法,并支撑LINQ查询语法。理解Lambda和匿名方法的关系,能帮助我们更自然地操作集合与数据流。

C#怎么使用Lambda表达式?Lambda和匿名方法的写法及LINQ应用详解

一、匿名方法的基本写法

在Lambda出现之前,C#使用delegate关键字定义匿名方法。匿名方法允许在不需要单独声明方法名的情况下,把一段逻辑直接赋给委托变量。这种方式在事件处理或临时回调中非常实用,但语法相对啰嗦。

下面代码展示了如何用匿名方法创建一个接受两个int参数并返回和的委托:

using System;

class Program
{
    static void Main()
    {
        // 使用匿名方法创建委托
        Func<int, int, int> add = delegate(int a, int b)
        {
            return a + b;
        };

        Console.WriteLine(add(3, 5)); // 输出 8
    }
}

从上面可以看出,匿名方法必须显式写出delegate关键字和参数类型。虽然它避免了定义独立方法,但当逻辑很简单时,这种写法显得不够轻量。另外,匿名方法无法直接转为表达式树,只能在运行时作为委托执行。

二、Lambda表达式的语法形式

Lambda表达式用 => 符号连接参数列表和方法体,编译器会根据上下文推断参数类型。它既能写成表达式体(单行返回值),也能写成语句块(多行逻辑),使用上比匿名方法更灵活。

以下示例用Lambda重写了上面的加法委托,并演示了无参数、单参数和多参数的几种形式:

using System;

class Program
{
    static void Main()
    {
        // 多参数语句块 Lambda
        Func<int, int, int> add = (a, b) =>
        {
            return a + b;
        };

        // 单参数表达式 Lambda,类型由编译器推断
        Func<int, int> square = x => x * x;

        // 无参数 Lambda
        Action printHello = () => Console.WriteLine("Hello");

        Console.WriteLine(add(3, 5));
        Console.WriteLine(square(4));
        printHello();
    }
}

当Lambda只有单个参数时,括号可以省略;方法体若只有一条返回语句,可写成表达式形式而不写return。这种简洁性让Lambda非常适合作为高阶函数的入参。需要注意的是,如果委托目标类型是表达式树(如Expression<Func<int,bool>>),Lambda会被编译为数据结构而非可执行IL,这正是LINQ to SQL等场景的基础。

Lambda与匿名方法的区别

二者核心区别在于:匿名方法只能用delegate声明且不能用于表达式树;Lambda可被编译器转换为委托或表达式树,并支持更自然的类型推断。在旧代码中还能见到匿名方法,但新项目基本都用Lambda。

特性匿名方法Lambda表达式
关键字delegate=>
类型推断需显式写参数类型多数情况可推断
表达式树支持不支持支持

三、在LINQ中的典型应用

LINQ大量依赖Lambda作为查询运算符的参数。无论是基于IEnumerable的内存查询,还是基于IQueryable的数据库查询,Lambda都用来描述筛选、投影、排序等逻辑。下面以List操作为例展示常见用法。

假设有一个学生集合,我们要筛选出分数大于80的学生姓名,并按分数降序排列后输出:

using System;
using System.Collections.Generic;
using System.Linq;

class Student
{
    public string Name { get; set; }
    public int Score { get; set; }
}

class Program
{
    static void Main()
    {
        List<Student> students = new List<Student>
        {
            new Student { Name = "张三", Score = 90 },
            new Student { Name = "李四", Score = 75 },
            new Student { Name = "王五", Score = 85 }
        };

        // Where 用 Lambda 筛选,Select 投影,OrderByDescending 排序
        var result = students
            .Where(s => s.Score > 80)
            .OrderByDescending(s => s.Score)
            .Select(s => s.Name);

        foreach (var name in result)
        {
            Console.WriteLine(name);
        }
        // 输出:张三 王五
    }
}

在上面的链式调用中,s => s.Score > 80是一个返回bool的Lambda,作为Where的筛选条件;s => s.Score提取排序键;s => s.Name把对象转为姓名字符串。这种写法比早期foreach加临时列表的代码短得多,也更容易阅读。

如果换成匿名方法,同样的逻辑会写成delegate(Student s) { return s.Score > 80; },不仅冗长,而且在IQueryable场景下根本无法编译。因此Lambda几乎是LINQ不可或缺的一部分。

Lambda捕获外部变量

Lambda可以捕获方法内的局部变量,这点和匿名方法一致。但要注意,被捕获的变量生命周期会延长到委托被回收为止,若在不经意间形成长生命周期引用,可能导致内存占用偏高。

using System;

class Program
{
    static void Main()
    {
        int threshold = 60;
        Func<int, bool> isPass = score => score >= threshold;
        Console.WriteLine(isPass(75)); // True
    }
}

上述代码中threshold被Lambda捕获,编译器会生成一个隐藏类来保存它。理解这一点有助于排查闭包相关的性能或逻辑问题。

四、常见写法误区与建议

新手常把Lambda体写成多行却忘了加大括号和return,或者把本该用于表达式树的Lambda误用在委托场景。建议明确变量目标类型:如果是List等内存集合,用Func或Action委托即可;如果传给EF Core等ORM,要确保Lambda能被翻译成SQL,避免调用本地方法。

另外,当逻辑较复杂时,不要把过长代码塞进Lambda,可以提取为命名方法再传入,保证可读性。匿名方法如今仅在维护老代码时可见,新开发统一使用Lambda能减少语法分歧。

C#_Lambda匿名方法LINQ修改时间:2026-08-06 11:54:30

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。