概述
微软在发布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 == "线上");
发表评论
登录用户才能发表评论, 请 登 录 或者 注册