首页 / 教程列表 / LINQ教程 / C#中的Lambda表达式

C#中的Lambda表达式

1420 更新于: 2021-11-02 读完约需 10 分钟

概述

微软在发布C# 3.0(.NET Framework 3.5)引入了LINQ特性的同时,也一起引入了Lambda表达式。Lambda表达式是使用一些特殊语法来表示匿名方法的一种更简洁的方式。

也就是说,你可以使用Lambda表达式来创建匿名函数。使用Lambda声明操作符=>将Lambda的形参列表与其函数体分开,形式如下:

1.表达式Lambda,它的主体是一个表达式:

(input-parameters) => expression

无参的Lambda表达式示例:

DelHello hello = () => Console.WriteLine("Hello Rector.");

2.语句Lambda,它的主体是一个语句块:

(input-parameters) => { <sequence-of-statements> }

示例如下:

DelHello hello = () =>
{
    var name = Console.ReadLine();
    Console.WriteLine($"Hello {name}.");
};

要创建Lambda表达式,需要在Lambda操作符(=>)的左侧指定输入参数(如果有的话),在另一侧指定表达式或语句块。

Lambda表达式与委托

Lambda表达式是一种特殊的委托,任何Lambda表达式都可以转换为委托类型。可以将Lambda表达式转换为的委托类型由其参数和返回值的类型定义。

如果Lambda表达式没有返回值,则可以将其转换为Action委托类型;否则,它可以转换为Func委托类型。

例如,具有两个参数且不返回值的Lambda表达式可以转换为Action<T1,T2>委托。

具有一个参数并返回值的Lambda表达式可以转换为Func<T,TResult>委托。在下面的示例中,Lambda表达式x => x * x指定名为x的参数并返回x平方的值,该表达式被分配给委托类型的变量:

Func<int, int> square = x => x * x;
Console.WriteLine(square(5));
// 输出结果:
// 25

表达式Lambda也可以转换为表达式树类型,如下面的示例所示:

System.Linq.Expressions.Expression<Func<int, int>> e = x => x * x;
Console.WriteLine(e);
// 输出结果:
// x => (x * x)

可以在任何需要委托类型或表达式树实例的代码中使用Lambda表达式,例如作为Task.Run(Action)方法的参数来传递应该在后台执行的代码。当你用C#编写LINQ时,你也可以使用Lambda表达式,如下例所示:

int[] numbers = { 2, 3, 4, 5 };
var squaredNumbers = numbers.Select(x => x * x);
Console.WriteLine(string.Join(" ", squaredNumbers));
// 输出结果:
// 4 9 16 25

在没有Lambda表达式之前,委托的用法是这样的:

using System;

namespace ConsoleApp2
{
    public class Program
    {
        // 1.定义一个委托
        delegate void DelHello();
        // 2.创建一个与委托返回类型(这里是无返回值)匹配的方法
        static void HelloMethod()
        {
            Console.WriteLine("Hello Rector.");
        }

        static void Main()
        {
            // 3.声明一个DelHello类型的委托,并赋值为HelloMethod
            DelHello hello = HelloMethod;
            // 4.调用委托
            hello();
            Console.ReadKey();
        }

    }
}

使用Lambda表达式的委托可以是这样的:

using System;

namespace ConsoleApp2
{
    public class Program
    {
        // 1.定义一个委托
        delegate void DelHello();

        static void Main()
        {
            // 3.声明一个DelHello类型的委托,并赋值为HelloMethod
            DelHello hello = () => Console.WriteLine("Hello Rector.");
            // 4.调用委托
            hello();
            Console.ReadKey();
        }

    }
}

Lambda表达式的输入参数

将Lambda表达式的输入参数包含在括号中,空括号表示无参数:

Action action = () => Console.WriteLine("Hello action");
action();

以上Lambda表示为无参数,无返回值。

如果需要传入一个参数,并且有返回值,那么可能是以下形式的Lambda表达式:

Func<double, double> cube = x => x * x * x;
cube(2);

上文已提到,使用Func表示有返回值的Lambda表达式,其中第一个参数表示传入参数类型,最后一个参数表示返回值类型。

如果有2个传入参数,则如下:

Func<int, int, bool> testForEquality = (x, y) => x == y;

有时编译器不能推断输入参数的类型,可以显式指定类型,如下面的示例所示:

Func<int, string, bool> isTooLong = (int x, string s) => s.Length > x;

输入参数类型必须是全部显式或全部隐式的;否则,将发生CS0748编译器错误。

从c# 9.0开始,您可以使用弃元为Lambda表达式指定两个或多个表达式中没有使用的输入参数:

Func<int, int, int> constant = (_, _) => 42;

当使用Lambda表达式来提供事件处理程序时,Lambda的弃元参数可能很有用。

LINQ与Lambda表达式

通常Lambda表达式与LINQ查询一起使用。可枚举静态类包括接受Func<TSource,bool>的IEnumerable<T>的Where扩展方法,bool>。因此,IEnumerable<Order,bool>集合的Where()扩展方法需要传递Func<Order,bool>,如下所示:

那么,从订单集合中筛选来源(Source)为”线上”的Where()方法可以如下:

Func<Order, bool> orderPredicate = (o) => o.Source == "线上";
var result = orders.Where(orderPredicate);

简写的方式如下:

var result = orders.Where((o) => o.Source == "线上");

版权声明:本作品系原创,版权归码友网所有,如未经许可,禁止任何形式转载,违者必究。

本文永久链接码友网 » LINQ教程 » C#中的Lambda表达式 分享:

发表评论

登录用户才能发表评论, 请 登 录 或者 注册