引言
本章将介绍Predicate
目录
一、委托类型的来由
二、建立委托类
三、委托使用方式
四、深入解析事件
五、Lambda 表达式
五、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
早在Framework 2.0 的时候,微软就为 List
public T Find ( Predicate
public List
在这些方法中存在一个Predicate
public delegate bool Predicate
在下面例子中,Predicate 委托绑定了参数为Person类的方法Match作为查询条件,然后使用 FindAll 方法查找到合适条件的 List
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 Listlist = GetList(); 6 //绑定查询条件
7 Predicatepredicate = new Predicate (Match); 8 List result = list.FindAll(predicate); 9 Console.WriteLine(“Person count is : ” + result.Count); 10 Console.ReadKey(); 11 } 12 //模拟源数据
13 static ListGetList() 14 { 15 var personList = new List (); 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
Action 支持0~16个参数,可以按需求任意使用。
public delegate void Action()
public delegate void Action
public delegate void Action
public delegate void Action
............
public delegate void Action
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
public delegate TResult Func
public delegate TResult Func
public delegate TResult Func
............
public delegate TResult Func
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
注意,此处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
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
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
相比之下,使用Lambda表达式,不需要定义Predicate
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 ListpersonList = GetList(); 6
7 //查找年龄少于30年的人 8 Listresult=personList.FindAll((person) => person.Age =< 30); 9 Console.WriteLine("Person count is : " + result.Count); 10 Console.ReadKey(); 11 } 12 13 //模拟源数据
14 static ListGetList() 15 { 16 var personList = new List (); 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 的长处。
但 LINQ 涉及到分部类,分部方法,IEnumerable
通过这一节的介绍,希望能够帮助大家更深入地了解 Lambda 的使用。
回到目录
本章小结
本章主要介绍了委托(Delegate)的使用,委托对象是一个派生自 System.MultcastDelegate 的类,它能通过 Invoke 方式进行同步调用,也可以通过 BeginInvoke,EndInvoke 方式实现异步调用。而事件(Event)属于一种特殊的委托,它与委托类型同步使用,可以简化的开发过程。
最后,本文还介绍了匿名方法的使用方式,以及 Lambda 表达式的由来。
希望本篇文章对相关的开发人员有所帮助。对JAVA与.NET开发有兴趣的朋友欢迎加入QQ群:162338858
C#综合揭秘
细说进程、应用程序域与上下文
细说多线程(上)
细说多线程(下)
细说事务
深入分析委托与事件