Lambda表达式(第六章)
C#支持内联处理事件,通过直接把一段代码语句赋值给事件(使用匿名方法),而不是构建被底层委托调用的独立方法。Lambda表达式只是用更简单的方式来写匿名方法,彻底简化了对.net委托类型的使用。
为了对Lambda表达式的研究做准备,先看如下program类型的新方法:
static void AnonymousMethodSyntax() { //建立整数列表 List<int> list=new List(); list.AddRange(new int[]{20,1,4,8,9,44}); //现在使用匿名方法 List<int> evenNumbers=list.FindAll(delegate(int i) { return (i%2)==0; }); ConsoleWriteLine("Here are your even numbers:"); foreach(int evenNumber in evenNumbers) { Console.Write("{0}\t",evenNumber); } Console.WriteLine(); }
以上代码我们并不是首先创建一个Predicate<T>委托类型,然后编写一个独立方法,而是使用了一个匿名方法。虽然这是正确方向,但是仍然需要使用关键字delegate(或者一个强类型化的Predicate<T>,而且还需要保证输入参数百分之百匹配。我们认为,定义匿名方法的语法还是有点冗长。下面代码可以说明这个问题:
List<int> evenNumbers =list.FindAll( delegate(int i) { return (i%2)==0; } );
我们可以用Lambda表达式进一步简化方法FindAll()的调用。使用新方法时,底层委托语法将会消失得无影无踪:
static void LambdaExpressionSyntax() { //建立整数列表 List<int> list=new List(); list.AddRange(new int[]{20,1,4,8,9,44}); //现在使用拉姆达表达式 List<int> evenNumbers=list.FindAll(i=>(i%2)==0); ConsoleWriteLine("Here are your even numbers:"); foreach(int evenNumber in evenNumbers) { Console.Write("{0}\t",evenNumber); } Console.WriteLine(); }
在深入了解表达式的语法前,我们需要知道Lambda表达式可以应用于任何匿名方法可以应用的场合,而且比匿名方法更节省编码时间。其实C#编译器只是把表达式翻译为使用委托Predicate<T>的普通匿名方法而已。
使用多个语句处理参数
当表达式必须使用多行代码处理参数时,你可以使用一对花括号确定这些语句的范围:
static void LambdaExpressionSyntax() { //建立整数列表 List<int> list=new List(); list.AddRange(new int[]{20,1,4,8,9,44}); //现在使用语句块编写拉姆达表达式 List<int> evenNumbers=list.FindAll( { Console.WriteLine("value of i is currently:{0}",i); bool isEven=((i%2)==0); return isEven; }); ConsoleWriteLine("Here are your even numbers:"); foreach(int evenNumber in evenNumbers) { Console.Write("{0}\t",evenNumber); } Console.WriteLine(); }
使用Lambda表达式重新编写CarDelegate示例
先看CarDelegate的简化版本,它使用传统的委托语法响应每个回调:
class Program { static void main(string[] args) { Console.Write("####More Fun With Lambdas####\n"); Car cl=new Car("SlugBug",100,10); cl.OnAboutToBlow(new Car.AboutToBlow(CarAboutToBlow)); cl.OnExploded(new Car.Exploded(CarExploded)); Console.WriteLine("Speed up"); for(int i=0;i<7;i++) cl.Accelerate(20); Console.ReadLine(); } //委托目标 public static void CarAboutToBlow(string msg) { Console.WriteLine(msg); } public static void CarExploded(stirng msg) { Console.WriteLine(msg);} }
下面是使用匿名方法的语法重写的Main
class Program { static void main(string[] args) { Console.Write("####More Fun With Lambdas####\n"); Car cl=new Car("SlugBug",100,10); cl.OnAboutToBlow(delegate(string msg){Console.WriteLine(msg);}); cl.OnExploded(delegate(string msg){Console.WriteLine(msg);}); Console.WriteLine("Speed up"); for(int i=0;i<7;i++) cl.Accelerate(20); Console.ReadLine(); } }
下面是使用Lambda表达式重新编写的Main():
class Program { static void main(string[] args) { Console.Write("####More Fun With Lambdas####\n"); Car cl=new Car("SlugBug",100,10); cl.OnAboutToBlow(msg=>{Console.WriteLine(msg);}); cl.OnExploded(msg=>{Console.WriteLine(msg);}); Console.WriteLine("Speed up"); for(int i=0;i<7;i++) cl.SpeedUp(20); Console.ReadLine(); } }
含有多个(或零个)参数的Lambda表达式
假设SimpleMath有如下更新
public class SimpleMath { public delegate void MathMessage(string msg,int result); private MathMessage mmDelegate; public void SetMathHandler(MathMessage target) { mmDelegate=target; } public int Add(int x,int y) { if(mmDelegate!=null) mmDelegate.Invoke("Adding has completed!",x+y); } } //我们看到,委托MathMessage需要两个参数。使用Lambda表达式的Main()如下: static void Main(string[] args) { //使用Lambda表达式注册委托 SimpleMath m=new SimpleMath(); m.SetMathHandler(msg,result)=> {Console.WriteLine("Message:{0},Result:{1},msg,result);}); //执行Lambda表达式 m.Add(10,10); Console.ReadLine(); }
以上只是学习的皮毛,有不当之处望各位博友指正。