.NET3.5新特性,Lambda表示式
隨VS 2005釋出的C#2.0引進了匿名方法的概念,允許在預期代理(delegate)值的地方用“行內(in-line)”程式碼塊(code blocks)來做替代。
Lambda表示式為編寫匿名方法提供了更簡明的函式式的句法,但結果卻在編寫LINQ查詢表示式時變得極其有用,因為它們提供了一個非常緊湊的而且類安全的方式來編寫可以當作引數來傳遞,在以後作運算的函式。
Lambda表示式的例子:
在我以前的擴充套件方法部落格貼子裡,我演示了你如何可以象下面這樣宣告一個簡單的Person類:
然後,我示範了你可以如何使用一些值來生成一個List
上面高亮標記的紅色 p => 表示式就是Lambda表示式。在上面的例子裡,我用第一個lambda來指定獲取特定人時所用的過濾條件,用第二個lambda來指定在計算平均年齡時該用Person物件的哪個值。
詳解Lambda表示式
理解Lambda表示式最容易的方法是把它們設想成編寫簡明的行內方法的方式。譬如,我上面編寫的例子可以使用C#2.0的匿名方法來編寫,象這樣:
上 面兩個匿名方法都接受一個Person型別的引數。第一個匿名方法返回一個布林值,表示Person的LastName是否是Guthrie,第二個匿名 方法返回一個整數值(返回那個人的年齡)。我們前面使用的lambda表示式的作用是一樣的,兩個表示式都接受一個Person型別的引數。第一個 lambda表示式返回一個布林值,第二個返回一個整數。
在C#裡,一個lambda表示式在句法上是寫成一個引數列表,隨後是 => 符號,隨後是表示式在呼叫時要運算的表示式或者語句塊:
params => expression
所以,當我們編寫這樣的lambda表示式時:
p => p.LastName == “Guthrie”
我們是想表示,我們在定義的Lambda接受一個引數p,要執行的程式碼表示式返回p.LastName的值是否等於“Guthrie”。 我們將引數命名為p是不相干的,我也可以很容易地將其命名為o,x,foo,或者我想要的任何名字。
不 象匿名方法要求引數型別是明確地指明的,Lambda表示式允許省略引數型別,而允許它們根據用法來推斷出型別。譬如,當我編寫 p=>p.LastName == “Guthrie” 這個lambda表示式時,編譯器推斷出p引數屬於Person型別,因為當前的Where擴充套件方法的物件是個範型的List集合。
Lambda引數的型別可以在編譯時和被Visual Studio的intellisense引擎推斷出來,這意味著在編寫lambda時你將獲得完全的intellisense 和編譯時檢查。譬如,注意當我在下面健入 p. 時,Visual Studio Orcas是如何提供intellisense完成的,因為它知道 p 是 Person型別:
注: 假如你要給一個Lambda表示式明確地宣告引數的型別的話,你可以在Lambda參數列裡的引數名字前宣告引數型別,象這樣:
針對框架開發人員的高階內容:Lambda表示式樹 (Lambda Expression Trees)
從 一個框架開發人員(framework developer)的角度來看,使得Lambda表示式特別強有力的事情之一是,它們既可以以基於IL的方法的形式被編譯成程式碼代理(code delegate),或者也可以編譯成一個表示式樹(expression tree)物件,然後在執行時用來分析,轉換或者最佳化表示式。
能將Lambda表示式編譯成一個表示式樹物件是個強大無比的機制,將促成許多使用場景,包括使用能提供編譯時句法檢查和VS intellisense的統一的查詢語言來建立支援豐富資料查詢的高效能物件對映器(無論是關聯式資料庫,活動目錄,還是web服務)之能力。
從Lambda表示式到程式碼代理 (Code Delegates)
上 面的Where擴充套件方法是個將Lambda表示式編譯成程式碼代理(code delegate)的例子(意即它是編譯成IL的,可以以代理的形式呼叫)。支援象上面那樣過濾任何IEnumerable集合的Where()擴充套件方法 可以使用下面這樣的擴充套件方法程式碼來實現:
上面的Where()擴充套件方法接受一個 Func
從Lambda表示式到表示式樹
當我們要想針對類似我們的列表集合一樣的記憶體中的資料做運算時,把lambda表示式編譯成程式碼代理是恰如其分的。但考慮一下你想要查詢資料庫裡的資料的情形(下面的程式碼是使用Orcas中內建的LINQ到SQL物件關係對映器寫成的) :
這裡,我要從資料庫裡取出一串強型別的Product物件,我向Where()擴充套件方法表示,要透過一個Lambda表示式來做過濾。
我絕對不想 要看到發生的是,從資料庫裡取回所有的產品記錄,將它們放在一個區域性的集合裡,然後在記憶體裡對它執行Where()擴充套件方法來進行過濾。這麼做效率極其不 高,對大資料庫的擴縮性將是極差的。而我希望的是,LINQ到SQL的ORM將我上面的Lambda過濾條件翻譯成SQL表示式,然後在遠端的資料庫裡進 行過濾性查詢。那樣的話,我只返回那些符合查詢條件的記錄,這樣的資料庫查詢效率是非常高的。
框架開發人員可以透過宣告他們的Lambda表示式引數是個Expression
注意上面我是怎麼把我們在先前用過的同樣的 p=>p.LastName == “Guthrie” Lambda表示式,但這次將其賦值給一個 Expression
在LINQ到SQL的情形下,它會將這個Lambda過濾語句翻譯成標準的關係SQL語句,來對資料庫進行操作(從邏輯上來說,一個“SELECT * from Products where UnitPrice
IQueryable
為 幫助框架開發人員建立可查詢的資料提供器,LINQ提供了 IQueryable
結語
希 望上面的貼子內容對如何考慮和使用Lambda表示式提供了基本的理解。當與Orcas中System.Linq名稱空間下提供的內建標準查詢擴充套件方法結 合使用時,它們提供了一個非常好的方式來對任何型別的資料進行查詢和互動,同時還保持了對完整的編譯時檢查和intellisense的支援。
通 過利用由Lambda提供的對錶達式樹的支援,以及 IQueryable
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/1806/viewspace-2801228/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- JDK1.8新特性--Lambda表示式JDK
- Java 8新特性(一):Lambda表示式Java
- jdk1.8新特性:Lambda表示式JDK
- JDK 1.8 新特性之Lambda表示式JDK
- JDK1.8新特性之Lambda表示式JDK
- Java8新特性(1):Lambda表示式Java
- JDK1.8新特性之Lambda表示式()->JDK
- Java8新特性(一)-Lambda表示式Java
- java8 新特性之Lambda 表示式Java
- JDK新特性-Lambda表示式的神操作JDK
- java-反射,介面新特性,Lambda表示式Java反射
- Java8 新特性之 Lambda 表示式Java
- jdk1.8 新特性之 lambda表示式JDK
- C++11新特性之Lambda表示式C++
- .net framework3.5新特性:Lambda表示式Framework
- JDK1.8的新特性之Lambda表示式JDK
- java8新特性之lambda表示式(一)Java
- jdk1.8 新特性之 如何寫lambda表示式JDK
- Java8新特性第1章(Lambda表示式)Java
- java8特性-lambda表示式Java
- Java8新特性——從Lambda表示式到Stream流Java
- Java 8新特性:lambda表示式(四)轉載總結Java
- 【原創】.net framework3.5新特性1:Lambda表示式Framework
- java8的新特性之lambda表示式和方法引用Java
- JDK8+的lambda(λ)表示式特性JDK
- Java 8 流特性和 Lambda 表示式Java
- C#10新特性-lambda 表示式和方法組的改進C#
- JDK1.8新特性:Lambda表示式語法和內建函式式介面JDK函式
- C#特性-匿名方法和Lambda表示式C#
- 深圳Java培訓學習:Java8.0新特性之Lambda表示式Java
- 好程式設計師分享java8新特性之Lambda表示式程式設計師Java
- JDK1.8最新特性--Lambda表示式(重點)JDK
- lambda 表示式
- lambda表示式
- 【Java8新特性】Lambda表示式基礎語法,都在這兒了!!Java
- 【Java新特性】Lambda表示式典型案例,你想要的的都在這兒了!!Java
- [Java學習筆記]JDK1.8新特性學習(一)Lambda表示式Java筆記JDK
- ?Java8新特性之Lambda表示式,函式式介面,方法引用和default關鍵字Java函式