说起lambda表达式,其实本质就是匿名函数一种效简化代码,一种方便的写法。下面我们通过代码的演化来增强对lamdaba表达式的理解。
在.NetFramework1.0我们的委托实例是这么写的:
public delegate void NoReturnNoPara();
//.NetFramework1.0 1.1
NoReturnNoPara method = new NoReturnNoPara(this.DoNothing);
NoReturnWithPara method = new NoReturnWithPara(this.Study);
method.Invoke(123, "董小姐");
private void DoNothing()
{
Console.WriteLine("This is DoNothing");
}
private void Study(int id, string name)
{
Console.WriteLine($"{id} {name} 学习.Net高级班");
}
到了.NetFramework2.0出现了匿名方法,使用delegate
关键字定义匿名方法
//.NetFramework2.0 匿名方法,delegate关键字
//可以访问局部变量
int i = 10;
NoReturnWithPara method = new NoReturnWithPara(delegate (int id, string name)
{
Console.WriteLine(i);
Console.WriteLine($"{id} {name} 学习.Net高级班");
});
method.Invoke(234, "Harley")
到了.NetFramework3.0 匿名方法吧delegate
关键字去掉,增加了一个箭头gose to,这个时候就已经是我们目前所看到lambda表达式了 参数列表=》方法体
NoReturnWithPara method = new NoReturnWithPara(
(int id, string name) =>
{
Console.WriteLine($"{id} {name} 学习.Net高级班");
});
method.Invoke(123, "Coder");
我们还可以再简化,省略掉参数类型因为有委托的方法签名,所以参数类型很容易推算出来
NoReturnWithPara method = new NoReturnWithPara(
(id, name) =>//省略参数类型,编译器的语法糖,虽然没写,编译时还是有的,根据委托推算
{
Console.WriteLine($"{id} {name} 学习.Net高级班");
});
method.Invoke(123, "加菲猫");
我们还可以进一步再省略,如果方法体只有一行,可以去掉大括号和分号
NoReturnWithPara method = new NoReturnWithPara(
(id, name) => Console.WriteLine($"{id} {name} 学习.Net高级班"));
//如果方法体只有一行,可以去掉大括号和分号
method.Invoke(123, "ZJ");
至此,基本上就是我们常见的lambda表达式的形式了。在上一章我们讲Action实例化的时候我们说过,可以省略到new Action
,编译器会自己动加上,结合匿名函数那就是:
NoReturnWithPara method = (id, name) => Console.WriteLine($"{id} {name} 学习.Net高级班");
method.Invoke(123, "大涛"); //new NoReturnWithPara可以省掉,也是语法糖,编译器自动加上
看来上面的演化过程,我们来总结一下,lambda表达式是什么?lambda表达式就是一个实例化委托的一个参数,就是一个方法。lambda表达式是匿名方法,但在编译的时候回去分配一个名字,这个我们可以在反编译中看到一些我们看不到的东西,匿名方法会产生一个私有的sealed类,在这里面增加了方法(带方法名)
NoReturnWithPara method = new NoReturnWithPara(this.Study);
method += this.Study;
method += (id, name) => Console.WriteLine($"{id} {name} 学习.Net高级班1");
method -= this.Study;
method -= (id, name) => Console.WriteLine($"{id} {name} 学习.Net高级班1");
//多播委托里面的lambda无法移除, 不是2个实例,其实是2个不同的方法
method.Invoke(345, "北纬23");
我们在订阅匿名方法后,无法在把其移除因为你-=
的匿名方法即时一模一样也是两个不同的方法。
上面演示的都没有返回值lambda的表达式或者匿名方法也是可以有返回值
Action action0 = () => {
};
Action<string> action1 = s => Console.WriteLine(s); //参数只有一个 可以省略小括号
Func<int> func0 = () => DateTime.Now.Month;//如果方法体只有一行,去掉大括号分号return
int iResult = func0.Invoke();