404 Not Found

404 Not Found


nginx

Lambda表达式

Lambda表达式概述

Lambda表达式是一种简洁的匿名函数语法,可以用更少的代码定义内联函数。它是C#函数式编程的核心特性,也是LINQ查询的基础。

Lambda语法

Lambda表达式的基本语法为:参数 => 表达式或语句块=>读作"goes to",将左侧参数映射到右侧的操作。

示例

CSHARP
using System;

class Program
{
    static void Main()
    {
        Func<int, int> square = x => x * x;
        Console.WriteLine(square(5));
    }
}
▶ 试一试
TEXT
25

单行Lambda与多行Lambda

单行Lambda直接返回表达式的结果,无需return关键字和花括号。多行Lambda需要花括号包裹语句块,并显式使用return返回。

示例

CSHARP
using System;

class Program
{
    static void Main()
    {
        Func<int, int> singleLine = x => x * x;
        Func<int, int> multiLine = x =>
        {
            int result = x * x;
            return result;
        };
        Console.WriteLine(singleLine(4));
        Console.WriteLine(multiLine(4));
    }
}
▶ 试一试
TEXT
16
16

类型推断

编译器通常可以根据上下文推断Lambda参数的类型,无需显式声明。当上下文不够明确时,可以手动指定类型。

示例

CSHARP
using System;

class Program
{
    static void Main()
    {
        Func<int, int> inferred = x => x + 1;
        Func<int, int> explicitType = (int x) => x + 1;
        Console.WriteLine(inferred(10));
        Console.WriteLine(explicitType(10));
    }
}
▶ 试一试
TEXT
11
11

Lambda与委托

Lambda表达式可以赋值给委托类型,这使它成为创建委托实例最简洁的方式。相比传统的匿名方法或显式委托实例化,Lambda更简短。

示例

CSHARP
using System;

delegate int Transform(int x);

class Program
{
    static void Main()
    {
        Transform doubleIt = x => x * 2;
        Transform addTen = x => x + 10;
        Console.WriteLine(doubleIt(3));
        Console.WriteLine(addTen(3));
    }
}
▶ 试一试
TEXT
6
13

Lambda与Func和Action

Func<T, TResult>表示有返回值的泛型委托,Action<T>表示无返回值的泛型委托。Lambda与它们配合使用非常常见。

示例

CSHARP
using System;

class Program
{
    static void Main()
    {
        Func<int, int, int> add = (a, b) => a + b;
        Action<string> greet = msg => Console.WriteLine(msg);
        Console.WriteLine(add(3, 7));
        greet("Hello");
    }
}
▶ 试一试
TEXT
10
Hello

Lambda与Predicate

Predicate<T>是返回bool的委托,常用于过滤和判断条件。Lambda表达式让它定义条件变得极其简洁。

示例

CSHARP
using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        var numbers = new List<int> { 1, 2, 3, 4, 5, 6 };
        Predicate<int> isEven = x => x % 2 == 0;
        var evens = numbers.FindAll(isEven);
        Console.WriteLine(string.Join(", ", evens));
    }
}
▶ 试一试
TEXT
2, 4, 6

闭包

Lambda表达式可以捕获外部变量,这称为闭包。被捕获的变量生命周期会随Lambda延长,即使原始作用域已结束,变量依然存活。

示例

CSHARP
using System;

class Program
{
    static void Main()
    {
        int factor = 3;
        Func<int, int> multiply = x => x * factor;
        Console.WriteLine(multiply(5));
        factor = 10;
        Console.WriteLine(multiply(5));
    }
}
▶ 试一试
TEXT
15
50
💡 闭包捕获的是变量本身而非变量的值,因此外部变量修改会影响Lambda的执行结果。

示例

CSHARP
using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        var actions = new List<Action>();
        for (int i = 0; i < 3; i++)
        {
            int copy = i;
            actions.Add(() => Console.WriteLine(copy));
        }
        foreach (var action in actions)
        {
            action();
        }
    }
}
▶ 试一试
TEXT
0
1
2
⚠️ 如果直接捕获循环变量i而不创建副本,所有Lambda将共享同一个i,最终输出均为3。创建局部副本可以避免此问题。

Lambda在LINQ中的应用铺垫

Lambda表达式是LINQ查询的核心。许多LINQ方法接受FuncExpression参数,Lambda提供了内联编写条件、投影和排序逻辑的简洁方式。

示例

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

class Program
{
    static void Main()
    {
        var numbers = new List<int> { 3, 7, 1, 9, 4, 6 };
        var big = numbers.Where(x => x > 5);
        var doubled = numbers.Select(x => x * 2);
        var sorted = numbers.OrderBy(x => x);
        Console.WriteLine(string.Join(", ", big));
        Console.WriteLine(string.Join(", ", doubled));
        Console.WriteLine(string.Join(", ", sorted));
    }
}
▶ 试一试
TEXT
7, 9, 6
6, 14, 2, 18, 8, 12
1, 3, 4, 6, 7, 9

表达式树简介

将Lambda赋值给Expression<TDelegate>时,编译器会生成一个数据结构(表达式树)而非可执行代码。表达式树可以被解析、修改和转换为其他形式,例如SQL查询。这是LINQ to SQL等技术的底层原理。

示例

CSHARP
using System;
using System.Linq.Expressions;

class Program
{
    static void Main()
    {
        Expression<Func<int, int>> expr = x => x * x + 1;
        Console.WriteLine(expr.Body);
        Console.WriteLine(expr.Parameters[0]);
        var compiled = expr.Compile();
        Console.WriteLine(compiled(4));
    }
}
▶ 试一试
TEXT
(x * x) + 1
x
17

ℹ️ Expression<Func<int,int>>Func<int,int>类型不同,前者是数据结构,后者是可执行委托。

❓ 常见问题

Q Lambda和匿名方法有什么区别?
A Lambda语法更简洁,支持类型推断和表达式树,匿名方法语法冗长且功能较少。 Q:Lambda参数什么时候必须显式指定类型? A:当编译器无法从上下文推断类型时,例如参数类型不明确或重载歧义时。 Q:闭包捕获的变量在什么时候释放? A:当所有引用该变量的Lambda都被垃圾回收后,捕获的变量才会释放。 Q:Expression和Func可以互相转换吗? A:Expression可以通过Compile()转为Func,但Func不能直接转回Expression。

📖 小节

  • Lambda语法为参数 => 表达式,简洁地定义匿名函数
  • 单行Lambda省略花括号和return,多行Lambda需要两者
  • 编译器可推断Lambda参数类型,必要时可显式声明
  • Lambda可直接赋值给自定义委托、Func、Action和Predicate
  • 闭包让Lambda捕获外部变量,变量生命周期随之延长
  • 循环中捕获变量需注意创建副本以避免意外共享
  • Lambda是LINQ方法的核心参数形式
  • 表达式树将Lambda表示为数据结构,可用于运行时分析和转换

📝 作业

  1. 编写一个Func<double, double, double>的Lambda,计算两个数的最大值
  2. 使用Action<string>的Lambda,输出一条带时间戳的日志信息
  3. 编写闭包示例:创建一个计数器函数,每次调用返回递增的整数
  4. 使用Where和Lambda从字符串列表中筛选出长度大于5的字符串
  5. 将一个Func<int, bool>的Lambda分别赋值给Func<int, bool>Expression<Func<int, bool>>,分别输出它们的GetType()结果
Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏