1. 程式人生 > >從C# 3.0說以人為本(四)—— Lambda表示式

從C# 3.0說以人為本(四)—— Lambda表示式


 重新回到那個用了很多次的語句:
  1. IEnumerable<int> numQuery = numbers.Where((number) => number % 2 == 0);

 
我們知道了Where是擴充套件方法,但是後面的(number) => number % 2 == 0又是什麼?功能一看就明白了,就是選擇是偶數的數字,但是深層機理又是什麼樣子的?
 
    查一下MSDN,原來這種表示式也是3.0新增的東東,叫Lambda表示式。它的語法小凡就不再介紹,MSDN中有很詳細的說明,再說也是狗尾續貂。但是,除了用Lambda表示式,像這樣的函式還能傳入什麼形參?是不是隻能用Lambda表示式了呢?
    答案當然是不會的,如果真的是這樣,那限制就太大了不是嗎?再查一下MSDN吧(MSDN果然才是解決問題的王道口牙),我們看到Where是被過載了好幾次的。
 
名稱 說明
Where(Expression<(Of <(Func<(Of <(TElement, Boolean>)>)>)>)) 基於謂詞篩選值序列。 (由 Queryable 定義。)
Where(Expression<(Of <(Func<(Of <(TElement, Int32, Boolean>)>)>)>)) 基於謂詞篩選值序列。將在謂詞函式的邏輯中使用每個元素的索引。 (由 Queryable 定義。)
Where(Func<(Of <(TElement, Boolean>)>)) 基於謂詞篩選值序列。 (由 Enumerable 定義。)
Where(Func<(Of <(TElement, Int32, Boolean>)>)) 基於謂詞篩選值序列。將在謂詞函式的邏輯中使用每個元素的索引。 (由 Enumerable 定義。)


 
其中有一個東西每個過載都會出現,就是Func<(Of <(TElement, Int32, Boolean>)>),好像是一個泛型,當然略有區別,有的是傳入2個有的是傳入3個型別。那Func<(Of <(TElement, Int32, Boolean>)>)又是什麼?再深入一下,原來是一個委託!

  1. publicdelegate TResult Func<T1, T2, TResult>( T1 arg1, T2 arg2 ) 

委託是什麼我想大家都用過,其實說穿了可以把它當成一個函式的指標(當然並不完全是,委託不等於函式指標,詳細請見《.NET Framework 程式設計》一書)。
走到這一步,恐怕大家都明白了,其實就是一個函式,這個函式用bool型別作為返回值,也就是判斷where條件是不是匹配。
針對上面那行程式碼,我們用純委託的方式再重現一次。

首先定義一個方法,完成校驗偶數的功能:

  1. privatestaticbool IsEvenNumber(int number){     return number % 2 == 0;}

然後把一開始的那行程式碼替換成

  1. IEnumerable<int> numQuery = numbers.Where(new Func<int,bool>(IsEvenNumber));

OK,效果是完全一樣的。這說明其實Lambda表示式其實在某種程度上就是一個匿名的函式,並且通過編譯器來自動識別型別換成泛型的委託。小凡認為,Where的內部程式碼邏輯就是遍歷每個numbers中的數字,並且呼叫傳入的委託方法來進行校驗。其實很簡單不是嗎?

雖然內部機理很簡單,但是如果真的要用委託,可能程式碼量馬上就增加了,相反用了Lambda表示式(當然事實上也需要編譯器的支援),就能又簡單又快捷的完成工作,為程式設計師考慮的語言才是好語言。

至此,從C# 3.0說以人為本就全部介紹完了,其中介紹了C# 3.0新增的LINQ和Lambda表示式,其它的一些新特性比如匿名型別等等就不描述了,謝謝大家。