Lambda 表达式
5.1 Lambda 的意义
在Framework 2.0 以前,声明委托的唯一方法是通过方法命名,从Framework 2.0 起,系统开始支持匿名方法。
通过匿名方法,可以直接把一段代码绑定给事件,因此减少了实例化委托所需的编码系统开销。
而在 Framework 3.0 开始,Lambda 表达式开始逐渐取代了匿名方法,作为编写内联代码的首选方式。总体来说,Lambda 表达式的作用是为了使用更简单的方式来编写匿名方法,彻底简化委托的使用方式。
5.2 回顾匿名方法的使用
匿名方法的使用已经在4.4节简单介绍过,在此回顾一下。
使用下面的方式,可以通过匿名方法为Button的Click事件绑定处理方法。
1 static void Main(string[] args)
2 {
3 Button btn = new Button();
4 btn.Click+=delegate(object obj,EventArgs e){
5 MessageBox.Show("Hello World !");
6 };
7 }
总是使用 delegate(){......} 的方式建立匿名方法,令人不禁感觉郁闷。于是从Framework 3.0 起, Lambda 表达式开始出现。
5.3 简单介绍泛型委托
在介绍 Lambda 表达式前,先介绍一下常用的几个泛型委托。
5.3.1 泛型委托 Predicate<T>
早在Framework 2.0 的时候,微软就为 List<T> 类添加了 Find、FindAll 、ForEach 等方法用作数据的查找。
public T Find ( Predicate<T> match)
public List<T> FindAll(Predicate<T> match)
在这些方法中存在一个Predicate <T> 表达式,它是一个返回bool的泛型委托,能接受一个任意类型的对象作为参数。
public delegate bool Predicate<T>(T obj)
在下面例子中,Predicate 委托绑定了参数为Person类的方法Match作为查询条件,然后使用 FindAll 方法查找到合适条件的 List<Person> 集合。
1 class Program
2 {
3 static void Main(string[] args)
4 {
5 List<Person> list = GetList();
6 //绑定查询条件
7 Predicate<Person> predicate = new Predicate<Person>(Match);
8 List<Person> result = list.FindAll(predicate);
9 Console.WriteLine(“Person count is : ” + result.Count);
10 Console.ReadKey();
11 }
12 //模拟源数据
13 static List<Person> GetList()
14 {
15 var personList = new List<Person>();
16 var person1 = new Person(1,"Leslie",29);
17 personList.Add(person1);
18 ........
19 return personList;
20 }
21 //查询条件
22 static bool Match(Person person)
23 {
24 return person.Age <= 30;
25 }
26 }
27
28 public class Person
29 {
30 public Person(int id, string name, int age)
31 {
32 ID = id;
33 Name = name;
34 Age = age;
35 }
36
37 public int ID
38 { get; set; }
39 public string Name
40 { get; set; }
41 public int Age
42 { get; set; }
43 }
5.3.2 泛型委托 Action
Action<T> 的使用方式与 Predicate<T> 相似,不同之处在于 Predicate<T> 返回值为 bool , Action<T> 的返回值为 void。
Action 支持0~16个参数,可以按需求任意使用。
public delegate void Action()
public delegate void Action<T1>(T1 obj1)
public delegate void Action<T1,T2> (T1 obj1, T2 obj2)
public delegate void Action<T1,T2,T3> (T1 obj1, T2 obj2,T3 obj3)
............
public delegate void Action<T1,T2,T3,......,T16> (T1 obj1, T2 obj2,T3 obj3,......,T16 obj16)
1 static void Main(string[] args)
2 {
3 Action<string> action=ShowMessage;
4 action("Hello World");
5 Console.ReadKey();
6 }
7
8 static void ShowMessage(string message)
9 {
10 MessageBox.Show(message);
11 }
5.3.3 泛型委托 Func
委托 Func 与 Action 相似,同样支持 0~16 个参数,不同之处在于Func 必须具有返回值
public delegate TResult Func<TResult>()
public delegate TResult Func<T1,TResult>(T1 obj1)
public delegate TResult Func<T1,T2,TResult>(T1 obj1,T2 obj2)
public delegate TResult Func<T1,T2,T3,TResult>(T1 obj1,T2 obj2,T3 obj3)
............
public delegate TResult Func<T1,T2,T3,......,T16,TResult>(T1 obj1,T2 obj2,T3 obj3,......,T16 obj16)
1 static void Main(string[] args)
2 {
3 Func<double, bool, double> func = Account;
4 double result=func(1000, true);
5 Console.WriteLine("Result is : "+result);
6 Console.ReadKey();
7 }
8
9 static double Account(double a,bool condition)
10 {
11 if (condition)
12 return a * 1.5;
13 else
14 return a * 2;
15 }
5.4 揭开 Lambda 神秘的面纱
Lambda 的表达式的编写格式如下:
当中 “ => ” 是 Lambda 表达式的操作符,在左边用作定义一个参数列表,右边可以操作这些参数。
例子一, 先把 int x 设置 1000,通过 Action 把表达式定义为 x=x+500 ,最后通过 Invoke 激发委托。
1 static void Main(string[] args)
2 {
3 int x = 1000;
4 Action action = () => x = x + 500;
5 action.Invoke();
6
7 Console.WriteLine("Result is : " + x);
8 Console.ReadKey();
9 }
例子二,通过 Action<int> 把表达式定义 x=x+500, 到最后输入参数1000,得到的结果与例子一相同。
注意,此处Lambda表达式定义的操作使用 { } 括弧包括在一起,里面可以包含一系列的操作。
1 static void Main(string[] args)
2 {
3 Action<int> action = (x) =>
4 {
5 x = x + 500;
6 Console.WriteLine("Result is : " + x);
7 };
8 action.Invoke(1000);
9 Console.ReadKey();
10 }
例子三,定义一个Predicate<int>,当输入值大约等于1000则返回 true , 否则返回 false。与5.3.1的例子相比,Predicate<T>的绑定不需要显式建立一个方法,而是直接在Lambda表达式里完成,简洁方便了不少。
1 static void Main(string[] args)
2 {
3 Predicate<int> predicate = (x) =>
4 {
5 if (x >= 1000)
6 return true;
7 else
8 return false;
9 };
10 bool result=predicate.Invoke(500);
11 Console.ReadKey();
12 }
例子四,在计算商品的价格时,当商品重量超过30kg则打9折,其他按原价处理。此时可以使用Func<double,int,double>,参数1为商品原价,参数2为商品重量,最后返回值为 double 类型。
1 static void Main(string[] args)
2 {
3 Func<double, int, double> func = (price, weight) =>
4 {
5 if (weight >= 30)
6 return price * 0.9;
7 else
8 return price;
9 };
10 double totalPrice = func(200.0, 40);
11 Console.ReadKey();
12 }
例子五,使用Lambda为Button定义Click事件的处理方法。与5.2的例子相比,使用Lambda比使用匿名方法更加简单。
1 static void Main(string[] args)
2 {
3 Button btn = new Button();
4 btn.Click += (obj, e) =>
5 {
6 MessageBox.Show("Hello World!");
7 };
8 Console.ReadKey();
9 }
例子六,此处使用5.3.1的例子,在List<Person>的FindAll方法中直接使用Lambda表达式。
相比之下,使用Lambda表达式,不需要定义Predicate<T>对象,也不需要显式设定绑定方法,简化了不工序。
1 class Program
2 {
3 static void Main(string[] args)
4 {
5 List<Person> personList = GetList();
6
7 //查找年龄少于30年的人
8 List<Person> result=personList.FindAll((person) => person.Age =< 30);
9 Console.WriteLine("Person count is : " + result.Count);
10 Console.ReadKey();
11 }
12
13 //模拟源数据
14 static List<Person> GetList()
15 {
16 var personList = new List<Person>();
17 var person1 = new Person(1,"Leslie",29);
18 personList.Add(person1);
19 .......
20 return personList;
21 }
22 }
23
24 public class Person
25 {
26 public Person(int id, string name, int age)
27 {
28 ID = id;
29 Name = name;
30 Age = age;
31 }
32
33 public int ID
34 { get; set; }
35 public string Name
36 { get; set; }
37 public int Age
38 { get; set; }
39 }
当在使用LINQ技术的时候,到处都会弥漫着 Lambda 的身影,此时更能体现 Lambda 的长处。
本文转载自:http://www.cnblogs.com/leslies2/archive/2012/03/22/2389318.html#a5