C# 中的 Lambda 表达式详解

在 C# 中,lambda 表达式是一种强大且简洁的匿名函数表示方式,它自.NET 3.5 引入后,极大地改变了 C# 的编程风格,使代码更加简洁、灵活和易于阅读。

一、Lambda 表达式的基本概念

Lambda 表达式本质上是一种匿名方法,没有方法名和访问修饰符。它可以快速定义一个内联的函数,并且可以作为参数传递给其他方法,或者作为返回值从方法中返回。其语法结构为:(inputparameters) => expression or statement block

例如,以下是一个简单的 lambda 表达式,用于计算两个数的和:

Func<int, int, int> add = (a, b) => a + b;
Console.WriteLine(add(3, 5)); // 输出 8

二、Lambda 表达式的形式

1. 表达式 lambda

表达式 lambda 的主体是一个表达式,会返回表达式的结果。当 lambda 只有一个输入参数时,括号可以省略,否则括号是必须的。例如:

// 单个参数
Func<int, int> square = x => x * x;
Console.WriteLine(square(4)); // 输出 16

// 多个参数
Func<int, int, int> multiply = (x, y) => x * y;
Console.WriteLine(multiply(3, 4)); // 输出 12

2. 语句 lambda

语句 lambda 的主体是一个语句块,使用大括号括起来。语句 lambda 的主体可以包含任意数量的语句,但通常不会过多。例如:

Action<string> greet = name =>
{
    string greeting = $"你好,{name}";
    Console.WriteLine(greeting);
};
greet("张三");

三、Lambda 表达式与委托

任何 lambda 表达式都可以转换为委托类型。如果 lambda 表达式不返回值,则可以将其转换为 Action 委托类型之一;否则,可将其转换为 Func 委托类型之一。例如:

Action printHello = () => Console.WriteLine("Hello!");
printHello();

Func<int, string> convertToString = num => num.ToString();
Console.WriteLine(convertToString(100)); // 输出 "100"

四、Lambda 表达式中的闭包

Lambda 表达式可以访问其外部的变量,这称为闭包。外部变量的值在 lambda 表达式被定义时确定,并且在 lambda 表达式执行时使用。例如:

int outerValue = 10;
Func<int, int> addOuterValue = x => x + outerValue;
Console.WriteLine(addOuterValue(5)); // 输出 15

五、Lambda 表达式在 LINQ 中的应用

在 LINQ(Language Integrated Query)中,lambda 表达式被广泛使用。LINQ 提供了一种统一的查询语法,可以对各种数据源(如数组、列表、数据库等)进行查询和操作。以下是一些在 LINQ 中使用 lambda 表达式的示例:

1. Where 子句

用于筛选满足条件的元素。例如,从一个整数列表中筛选出大于 5 的数:

List<int> numbers = new List<int> { 1, 6, 3, 8, 2, 7 };
var filteredNumbers = numbers.Where(n => n > 5);
foreach (var num in filteredNumbers)
{
    Console.WriteLine(num);
}

2. Select 子句

用于选择和转换数据源中的元素。例如,将一个字符串列表中的每个元素转换为大写:

List<string> strings = new List<string> { "apple", "banana", "cherry" };
var upperCaseStrings = strings.Select(s => s.ToUpper());
foreach (var str in upperCaseStrings)
{
    Console.WriteLine(str);
}

3. OrderBy 和 OrderByDescending 子句

用于对数据源中的元素进行排序。例如,按升序和降序对一个整数列表进行排序:

List<int> numbers = new List<int> { 9, 3, 7, 2, 5 };
var ascendingOrder = numbers.OrderBy(n => n);
var descendingOrder = numbers.OrderByDescending(n => n);
foreach (var num in ascendingOrder)
{
    Console.WriteLine(num);
}
foreach (var num in descendingOrder)
{
    Console.WriteLine(num);
}

4. GroupBy 子句

用于对数据源中的元素进行分组。例如,根据字符串的首字母对一个字符串列表进行分组:

List<string> strings = new List<string> { "apple", "banana", "cherry", "avocado" };
var groupedStrings = strings.GroupBy(s => s[0]);
foreach (var group in groupedStrings)
{
    Console.WriteLine($"Group key: {group.Key}");
    foreach (var str in group)
    {
        Console.WriteLine(str);
    }
}

六、Lambda 表达式的高级特性

1. 类型推断

在编写 lambda 表达式时,通常不必为输入参数指定类型,编译器可以根据上下文自动推断参数的类型。但是,如果编译器无法正确推断类型,或者为了提高代码的可读性,可以显式指定参数的类型。例如:

// 隐式类型推断
Func<int, bool> isEven = num => num % 2 == 0;

// 显式类型指定
Func<int, bool> isGreaterThanFive = (int num) => num > 5;

2. 元组作为参数和返回值

从 C# 7.0 起,C# 语言提供对元组的内置支持。可以提供一个元组作为 lambda 表达式的参数,同时 lambda 表达式也可以返回一个元组。例如:

Func<(int, int, int), (int, int, int)> doubleValues = s => (2 * s.Item1, 2 * s.Item2, 2 * s.Item3);
var nums = (3, 7, 4);
var doubledNums = doubleValues(nums);
Console.WriteLine($"The set {nums} doubled: {doubledNums}");

3. 异步 lambda 表达式

通过使用 async 和 await 关键字,可以创建包含异步处理的 lambda 表达式。例如:

async Task Main()
{
    Func<Task> asyncLambda = async () =>
    {
        await Task.Delay(1000);
        Console.WriteLine("Async lambda executed.");
    };
    await asyncLambda();
}

七、总结

Lambda 表达式是 C# 中非常强大的特性,它使代码更加简洁、灵活,并且在 LINQ 和异步编程等场景中发挥着重要作用。通过合理地使用 lambda 表达式,可以提高代码的可读性和可维护性,同时也能够更方便地进行函数式编程。在实际开发中,我们应该根据具体的需求和场景,灵活地运用 lambda 表达式,以提高开发效率。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值