ZetCode

C# lambda 表达式

最后修改于 2025 年 5 月 14 日

本 C# lambda 表达式教程解释了如何在 C# 中使用 lambda 表达式来编写更简洁易懂的代码。

Lambda 表达式是一个匿名函数,它不绑定到标识符。 它可以用于任何需要委托类型的地方,从而允许进行内联函数定义,而无需显式声明单独的方法。 Lambda 表达式通常用于 LINQ 查询、事件处理和函数式编程。

与传统方法相比,Lambda 表达式能够实现更紧凑的语法,从而提高代码的可读性并减少样板代码。 它们对于定义完整方法不必要的短操作特别有用。

Lambda 表达式有两种主要形式

语法 描述
(输入参数) => 表达式 具有表达式主体的单行 lambda。
(输入参数) => { <语句序列> } 具有语句块的多行 lambda。

C# lambda 表达式简单示例

以下是一个包含 lambda 表达式的简单示例。

Program.cs
Func<int, int> square = x => x * x;
Func<int, int> cube = x => x * x * x;
Func<int, int> inc = x => x++;
Func<int, int, int> add = (x, y) => x + y;

Console.WriteLine(square(5));
Console.WriteLine(cube(5));
Console.WriteLine(inc(5));
Console.WriteLine(add(5, 7));

在此示例中,我们定义了四个函数。

Func<int, int> square = x => x * x;

Func 委托引用一个 lambda 表达式,该表达式对输入值求平方。 这是其他语言中纯函数的最近似等价物。

$ dotnet run
25
125
5
12

C# lambda 语句

Lambda 语句可以有多个语句,这些语句包含在 {} 大括号中。

Program.cs
Action<string> greet = name =>
{
    string greeting = $"Hello {name}!";
    Console.WriteLine(greeting);
};

greet("Pau");
greet("Lucia");

在此示例中,我们使用 Action 委托。 在等式的右侧,我们有一个 lambda 语句,它由两个语句组成。 Action 委托接受一个输入参数,并且不返回任何内容。

$ dotnet run
Hello Pau!
Hello Lucia!

C# lambda 表达式与数组

在以下示例中,我们将使用数组。

Program.cs
int[] vals = [1, -2, 3, 4, 0, -3, 2, 1, 3];

var v1 = Array.FindIndex(vals, x => x == 3);
Console.WriteLine(v1);

var v2 = Array.FindLastIndex(vals, x => x == 3);
Console.WriteLine(v2);

var positive = Array.FindAll(vals, x => x > 0);
Console.WriteLine(string.Join(",", positive));

数组函数需要一个谓词函数,该函数应用于数组的所有元素。

var positive = Array.FindAll(vals, x => x > 0);

我们将 lambda 表达式作为第二个参数传递给 FindAll 方法; 该表达式是一个谓词,对于大于零的值返回 true。

$ dotnet run
2
8
1,3,4,2,1,3

C# lambda 表达式与 LINQ

我们可以在许多 LINQ 方法中使用 lambda 表达式。

Program.cs
List<int> vals = [-1, 2, -2, 0, 3, 4, -5];

var squared = vals.Select(x => x * x);
Console.WriteLine(string.Join(", ", squared));

var filtered = vals.Where(x => x > 0);
Console.WriteLine(string.Join(", ", filtered));

在此示例中,我们在 LINQ 的 SelectWhere 方法中使用 lambda 表达式。

$ dotnet run
1, 4, 4, 0, 9, 16, 25
2, 3, 4

Lambda 默认参数

自 C# 12 以来,lambda 中的参数可以具有默认值。

Program.cs
var message = (string greet, string name = "there") => $"{greet} {name}!";

var res = message("Hi", "Tom");
Console.WriteLine(res);

var res2 = message("Hello");
Console.WriteLine(res2);

现在提供 name 参数是可选的。 可选参数必须遵循强制参数。

$ dotnet run
Hi Tom!
Hello there!

C# lambda 表达式数组

在以下示例中,我们创建一个 lambda 表达式数组。

Program.cs
Func<int, int>[] funs =
[
    x => x * x,
    x => ++x,
    x => --x
];

for (int i = 0; i < 6; i++)
{
    Console.WriteLine(funs[0](i));
    Console.WriteLine(funs[1](i));
    Console.WriteLine(funs[2](i));
    Console.WriteLine();
}

在此示例中,我们将三个 lambda 表达式放入一个数组中。 然后,在 for 循环中,我们将整数 0..5 传递给这三个 lambda 表达式。

C# lambda 表达式弃元

自 C# 9.0 以来,我们可以使用弃元 (_) 作为 lambda 和匿名方法的参数。

Program.cs
using System.Windows.Forms;
using System.Drawing;

namespace QuitButton;
 
class MyForm : Form
{
    private FlowLayoutPanel flowPanel = new();

    public MyForm()
    {
        InitComponents();
    }

    private void InitComponents()
    {
        Text = "Quit button";
        ClientSize = new Size(800, 450);

        flowPanel = new FlowLayoutPanel();

        flowPanel.Dock = DockStyle.Fill;
        flowPanel.BorderStyle = BorderStyle.FixedSingle;

        var button = new Button();
        button.Margin = new Padding(10, 10, 0, 0);

        button.Text = "Quit";
        button.AutoSize = true;
        button.Click += (_, _) => Close();

        flowPanel.Controls.Add(button);
        Controls.Add(flowPanel);

        CenterToScreen();
    }

    [STAThread]
    static void Main()
    {
        Application.SetHighDpiMode(HighDpiMode.SystemAware);
        Application.EnableVisualStyles();
        Application.Run(new MyForm());
    }
}

该示例是一个使用 Winforms 创建的简单 GUI 应用程序; 它仅在 Windows 上运行。

button.Click += (_, _) => Close();

由于我们不使用发送者对象和事件参数,因此我们可以使用弃元。

C# lambda 与闭包

Lambda 表达式可以捕获和使用来自其封闭范围的变量。 这称为闭包。

Program.cs
int factor = 3;
Func<int, int> multiply = x => x * factor;

Console.WriteLine(multiply(5));
factor = 4;
Console.WriteLine(multiply(5));

Lambda 表达式使用外部范围的变量 factor。 如果 factor 的值发生变化,则 lambda 会反映新值。

C# lambda 作为比较器

Lambda 可用于为集合定义自定义排序顺序,例如按长度对字符串进行排序。

Program.cs
List<string> words = ["pear", "apple", "banana", "kiwi"];

words.Sort((a, b) => a.Length.CompareTo(b.Length));
Console.WriteLine(string.Join(", ", words));

lambda (a, b) => a.Length.CompareTo(b.Length) 用作自定义比较器,以按字符串长度对列表进行排序。

C# lambda 具有多个参数和语句

Lambda 可以有多个参数和一个语句块,例如用于聚合值。

Program.cs
List<int> nums = [1, 2, 3, 4];

int sum = nums.Aggregate(0, (acc, x) => {

    int result = acc + x;
    Console.WriteLine($"Adding {x}, sum so far: {result}");
    return result;
});

Console.WriteLine($"Total: {sum}");

此示例在 Aggregate 中使用多参数、多语句 lambda 来对值求和并在每个步骤中打印进度。

在本文中,我们使用了 C# 中的 lambda 表达式。

来源

Lambda 表达式和匿名函数

作者

我叫 Jan Bodnar,我是一位充满热情的程序员,拥有丰富的编程经验。 自 2007 年以来,我一直在撰写编程文章。 迄今为止,我已经撰写了超过 1,400 篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出所有 C# 教程