一、Lambda简介:
Lambda是一个表达式,也可以说它是一个匿名函数,然而在使用它或是阅读Lambda代码的时候,却显得并不那么容易,因为它匿名,删减了一些必要的说明信息(比如方法名)。所有的lambda表达式都是用新的lambda运算符 “ => ”,可以叫他,“转到”或者 “成为”。运算符将表达式分为两部分,左边指定输入参数,右边是为计算表达式。
表达式:
1.一个参数: param=>expo
2.多个参数:(param-list)=>expo
优点:
- 在普通代码里几行的代码,在Lambda中只需要一行就可以解决。所以代码比以前更简洁了
- 可以在某一个方法内部定义,这样可以提高操作的便捷性
缺点:
- Lambda是一个匿名函数,因为是匿名,所以可读性变差了
- 有时候有多个Lambda嵌套(就像实例中的第3点一样),让程序变得难以理解
二、案例解析:细细研读
public class Person
{
public string Name { get; set; }
public int Age { get;set; } //年龄
}
class Program
{
public static List<Person> PersonsList()
{
List<Person> persons = new List<Person>();
for (int i = 0; i < 7; i++)
{
Person p = new Person() { Name = i + "儿子", Age = 8 - i, };//初始化7个对象
persons.Add(p);
}
return persons;
}
static void Main(string[] args)
{
List<Person> persons = PersonsList();
persons = persons.Where(p => p.Age > 6).ToList(); //所有Age年龄>6岁 的Person的集合
Person per = persons.SingleOrDefault(p => p.Age == 1); //Age=1的单个people类
persons = persons.Where(p => p.Name.Contains("儿子")).ToList(); //所有Name包含儿子的Person的集合
}
}
上面的代码很简洁,重点在最好三段代码用到Lambda表达式,下面我们来看下类似‘p=>p.Age>6’这样的表达式,到底是怎么回事?
首先我们先看明白‘委托’:
//委托 :超市
delegate int Chaoshi(int a);
static void Main(string[] args)
{
Chaoshi gwl = JieZhang; //结账委托给超市
Console.WriteLine(gwl(10) + ""); //打印 显示 10
Console.ReadKey();
}
//结账
public static int JieZhang(int a)
{
return a;
}
再看表达式:
//委托 超市
delegate int Chaoshi(int a);
static void Main(string[] args)
{
Chaoshi gwl = p => p ;// Chaoshi gwl = JieZhang;
Console.WriteLine(gwl(10) + ""); //打印10,表达式的应用
Console.ReadKey();
}
// Chaoshi gwl = JieZhang;
Console.WriteLine(gwl(10) + ""); //打印10,表达式的应用
Console.ReadKey();
}
最后,通过委托和表达式的两段代码,我们可以大致看出:其实表达式(p => p;)中的 p 就代表委托方法中的参数‘a’,而表达式符号右边的 p,就是委托方法中的返回结果。
下面再上两个稍微复杂点的理解理解:
1.多参数的 :
//委托 超市
delegate int Chaoshi(int a,int b);
static void Main(string[] args)
{
Chaoshi gwl = (p,z) => z-(p + 10);
Console.WriteLine(gwl(10,100) + ""); //打印结果显示80(z对应参数b,p对应参数a)
Console.ReadKey();
}
2. lambda主体运算复杂
/// 委托 超市
/// <param name="a">花费</param>
/// <param name="b">付钱</param>
/// <returns>找零</returns>
delegate int Chaoshi(int a,int b);
static void Main(string[] args)
{
Chaoshi gwl = (p, z) =>
{
int zuidixiaofei = 10;
if (p < zuidixiaofei)
{
return 100;
}
else
{
return z - p - 10;
}
};
Console.WriteLine(gwl(10,100) + ""); //打印结果显示80(z对应参数b,p对应参数a)
Console.ReadKey();
}
下面介绍一个系统指定 Fun <T> 泛型委托的用法:多个参数,前面的为委托方法的参数,最后一个参数为委托方法的返回类型。
static void Main(string[] args)
{
Func<int, string> gwl = p => p + 10 + "--string";
Console.WriteLine(gwl(10) + ""); //打印结果显示:‘20--string’
Console.ReadKey();
}
说明:我们可以看到,这里的p为int 类型参数, 然而lambda主体返回的是string类型的。
static void Main(string[] args)
{
Func<int, int, bool> gwl = (p, j) =>
{
if (p + j == 10)
{
return true;
}
return false;
};
Console.WriteLine(gwl(5,5) + ""); //打印结果显示‘True’
Console.ReadKey();
}
说明:从这个例子,我们能看到,p为int类型,j为int类型,返回值为bool类型。
三、(放大招)动态创建Lambda表达式树:
static void Main(string[] args)
{
//i*j+w*x
ParameterExpression a = Expression.Parameter(typeof(int),"i");//创建一个表达式树中的参数,作为一个节点,这里是最下层的节点
ParameterExpression b = Expression.Parameter(typeof(int),"j");
BinaryExpression be = Expression.Multiply(a,b); //这里i*j,生成表达式树中的一个节点,比上面节点高一级
ParameterExpression c = Expression.Parameter(typeof(int), "w");
ParameterExpression d = Expression.Parameter(typeof(int), "x");
BinaryExpression be1 = Expression.Multiply(c, d);
BinaryExpression su = Expression.Add(be,be1); //运算两个中级节点,产生终结点
Expression<Func<int, int, int, int, int>> lambda = Expression.Lambda<Func<int, int, int, int, int>>(su,a,b,c,d);
Console.WriteLine(lambda + ""); //打印结果:‘(i,j,w,x)=>((i*j)+(w*x))’
Func<int, int, int, int, int> f= lambda.Compile(); //将表达式树描述的lambda表达式,编译为可执行代码,并生成该lambda表达式的委托;
Console.WriteLine(f(1, 1, 1, 1) + ""); //打印结果:2
Console.ReadKey();
}