Lambda表達式
"Lambda表達式"是一個匿名函數,是一種高效的相似於函數式編程的表達式,Lambda簡化了開發中須要編寫的代碼量。它能夠包含表達式和語句,而且可用於建立委託或表達式目錄樹類型,支持帶有可綁定到委託或表達式樹的輸入參數的內聯表達式。全部Lambda表達式都使用Lambda運算符=>,該運算符讀做"goes to"。Lambda運算符的左邊是輸入參數(若是有),右邊是表達式或語句塊。Lambda表達式x => x * x讀做"x goes to x times x"。能夠將此表達式分配給委託類型,以下所示:編程
- delegate int del(int i);
- del myDelegate = x => x * x;
- int j = myDelegate(5); //j = 25
Lambda表達式Lambda表達式是由.NET 2.0演化而來的,也是LINQ的基礎,熟練地掌握Lambda表達式可以快速地上手LINQ應用開發。數據結構
Lambda表達式在必定程度上就是匿名方法的另外一種表現形式。爲了方便對Lambda表達式的解釋,首先須要建立一個People類,示例代碼以下。函數式編程
- public class People
- {
- public int age { get; set; } //設置屬性
- public string name { get; set; } //設置屬性
- public People(int age,string name) //設置屬性(構造函數構造)
- {
- this.age = age; //初始化屬性值age
- this.name = name; //初始化屬性值name
- }
- }
上述代碼定義了一個People類,幷包含一個默認的構造函數可以爲People對象進行年齡和名字的初始化。在應用程序設計中,不少狀況下須要建立對象的集合,建立對象的集合有利於對對象進行搜索操做和排序等操做,以便在集合中篩選相應的對象。使用List進行泛型編程,能夠建立一個對象的集合,示例代碼以下。函數
- List<People> people = new List<People>(); //建立泛型對象
- People p1 = new People(21,"guojing"); //建立一個對象
- People p2 = new People(21, "wujunmin"); //建立一個對象
- People p3 = new People(20, "muqing"); //建立一個對象
- People p4 = new People(23, "lupan"); //建立一個對象
- people.Add(p1); //添加一個對象
- people.Add(p2); //添加一個對象
- people.Add(p3); //添加一個對象
- people.Add(p4); //添加一個對象
上述代碼建立了4個對象,這4個對象分別初始化了年齡和名字,並添加到List列表中。當應用程序須要對列表中的對象進行篩選時,例如須要篩選年齡大於20歲的人,就須要從列表中篩選,示例代碼以下。post
- //匿名方法
- IEnumerable<People> results = people.Where
(delegate(People p) { return p.age > 20; });
上述代碼經過使用IEnumerable接口建立了一個result集合,而且該集合中填充的是年齡大於20的People對象。細心的讀者可以發如今這裏使用了一個匿名方法進行篩選,由於該方法沒有名稱,經過使用People類對象的age字段進行篩選。this
雖然上述代碼中執行了篩選操做,可是,使用匿名方法每每不太容易理解和閱讀,而Lambda表達式則更加容易理解和閱讀,示例代碼以下。spa
- IEnumerable<People> results = people.Where(People => People.age > 20);
上述代碼一樣返回了一個People對象的集合給變量results,可是,其編寫的方法更加容易閱讀,從這裏能夠看出Lambda表達式在編寫的格式上和匿名方法很是類似。其實,當編譯器開始編譯並運行時,Lambda表達式最終也表現爲匿名方法。設計
使用匿名方法並非建立了沒有名稱的方法,實際上編譯器會建立一個方法,這個方法對於開發人員來講是不可見的,該方法會將People類的對象中符合p.age>20的對象返回並填充到集合中。相同地,使用Lambda表達式,當編譯器編譯時,Lambda表達式一樣會被編譯成一個匿名方法進行相應的操做,可是與匿名方法相比,Lambda表達式更容易閱讀,Lambda表達式的格式以下。對象
- (參數列表)=>表達式或語句塊
上述代碼中,參數列表就是People類,表達式或語句塊就是People.age>20,使用Lambda表達式可以讓人很容易地理解該語句到底是如何執行的,雖然匿名方法提供了一樣的功能,卻不容易被理解。相比之下,People => People.age > 20卻可以很好地理解爲"返回一個年紀大於20的人"。其實,Lambda表達式並無什麼高深的技術,Lambda表達式能夠看做是匿名方法的另外一種表現形式。Lambda表達式通過反編譯後,與匿名方法並無什麼區別。blog
比較Lambda表達式和匿名方法,在匿名方法中,"("、")"內是方法的參數的集合,這就對應了Lambda表達式中的"(參數列表)",而匿名方法中"{"、"}"內是方法的語句塊,這對應了Lambda表達式中"=>"符號右邊的表達式或語句塊項。Lambda表達式也包含一些基本的格式,這些基本格式以下。
Lambda表達式能夠有多個參數、一個參數,或者沒有參數。其參數類型能夠隱式或者顯式。示例代碼以下:
- (x, y) => x * y //多參數,隱式類型=> 表達式
- x => x * 5 //單參數, 隱式類型=>表達式
- x => { return x * 5; } //單參數,隱式類型=>語句塊
- (int x) => x * 5 //單參數,顯式類型=>表達式
- (int x) => { return x * 5; } //單參數,顯式類型=>語句塊
- () => Console.WriteLine() //無參數
上述格式都是Lambda表達式的合法格式,在編寫Lambda表達式時,能夠忽略參數的類型,由於編譯器可以根據上下文直接推斷參數的類型,示例代碼以下。
- (x, y) => x + y //多參數,隱式類型=> 表達式
Lambda表達式的主體能夠是表達式也能夠是語句塊,這樣就節約了代碼的編寫。
【例2-5】傳統方法,匿名方法和Lamdba表達式對比。
(1) 建立控制檯應用程序LamdbaPrictice。
(2) 在程序中添加3個函數,這3個函數分別使用傳統的委託調用、使用匿名方法和Lamdba表達式方法完成同一功能,對比有什麼不一樣。代碼以下:
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- namespace LambdaDemo
- {
- class Program
- {
- static void Main(string[] args)
- {
- Console.WriteLine("傳統的委託代碼示例:");
- FindListDelegate();
- Console.Write("\n");
- Console.WriteLine("使用匿名方法的示例:");
- FindListAnonymousMethod();
- Console.Write("\n");
- Console.WriteLine("使用Lambda的示例:");
- FindListLambdaExpression();
-
- }
- //傳統的調用委託的示例
- static void FindListDelegate()
- {
- //先建立一個泛型的List類
- List<string> list = new List<string>();
- list.AddRange(new string[] { "ASP.NET課程","J2EE課程", "PHP課程", "數據結構課程" });
- Predicate<string> findPredicate = new Predicate<string>(IsBookCategory);
- List<string> bookCategory = list.FindAll(findPredicate);
- foreach (string str in bookCategory)
- {
- Console.WriteLine("{0}\t", str);
- }
- }
- //謂詞方法,這個方法將被傳遞給FindAll方法進行書書籍分類的判斷
- static bool IsBookCategory(string str)
- {
- return str.EndsWith("課程") ? true : false;
- }
- //使用匿名方法來進行搜索過程
- static void FindListAnonymousMethod()
- {
- //先建立一個泛型的List類
- List<string> list = new List<string>();
- list.AddRange(new string[] { "ASP.NET課程", "J2EE課程", "PHP課程", "數據結構課程" });
- //在這裏,使用匿名方法直接爲委託建立一個代碼塊,而不用去建立單獨的方法
- List<string> bookCategory = list.FindAll
- (delegate(string str)
- {
- return str.EndsWith("課程") ? true : false;
- }
- );
- foreach (string str in bookCategory)
- {
- Console.WriteLine("{0}\t", str);
- }
- }
- //使用Lambda來實現搜索過程
- static void FindListLambdaExpression()
- {
- //先建立一個泛型的List類
- List<string> list = new List<string>();
- list.AddRange(new string[] { "ASP.NET課程", "J2EE課程", "PHP課程", "數據結構課程" });
- //在這裏,使用了Lambda來建立一個委託方法
- List<string> bookCategory = list.FindAll((string str) => str.EndsWith("課程"));
- foreach (string str in bookCategory)
- {
- Console.WriteLine("{0}\t", str);
- }
- }
-
- }
- }
程序的運行結果如圖2-7所示。