對於從來沒接觸過lambda表達式的人來說,這個玩意很蛋疼,蛋疼的語法,蛋疼的外表,但是就和人一樣,如果長得太突出(丑),一般就會有大才,畢竟老天是公平的嘛!
在具體分析lambda之前,先說兩句:
1.lambda表達式不是必須的,因為其就是一個匿名函數,凡是通過lambda表達式可以完成的工作,都可以通過匿名函數來完成(當然,我們也知道,匿名函數也不是必須的)。
2.lambda表達式可以極大簡化我們對匿名函數的使用.
3.學習lambda表達式之前你最好對匿名函數、委托、泛型的概念有所了解。
MSDN定義:Lambda 表達式是一種可用於創建委托或表達式目錄樹類型的匿名函數。
通過上面的定義我們可以了解:
1.lambda表達式是匿名函數,只不過長得不太像而已,可以看成是進化版。
2.lambda表達式是用來創建委托或者目錄樹的匿名函數
目錄樹是何許人也,放到其他章節說,這里只說lambda表達式創建委托。
首先,創建一個委托
delegate int del(int arg);
然后創建一個符合這個委托定義的方法
static int Func1(int numb) { return numb + 10; }
創建委托del的實例,這里創建委托的方法我們用的是最基本的方法。
static void Main(string[] args) { del d1 = new del(Func1); Console.WriteLine(d1(10)); Console.ReadKey(); }
好,上面我們創建了委托del的實例。
我們知道如果一個方法可能只用一次,我們就沒必要單獨創建這個方法,而是可以使用匿名函數。那么我們假設Func就是那個只使用一次的函數,我們可以將上面的創建委托的實例的代碼改為使用匿名函數的版本。
static void Main(string[] args) { del d1 = delegate(int numb) { return numb + 10; }; Console.WriteLine(d1(10)); Console.ReadKey(); }
分析一下這個匿名函數:delegaet關鍵字、匿名函數的參數的類型和形參名稱、函數體,還能不能更簡單一點呢?繼續看,主角來了
static void Main(string[] args) { del d1 = p => p + 10; Console.WriteLine(d1(10)); Console.ReadKey(); }
p=>p+10就是lambda表達式,我們來分析一下,很簡單的喲
1.=>讀作“成為”、"轉成",英文讀作"goes to"
2.=>左邊的p表示調用方法時給方法傳入的參數
3.=>右邊的p+10,表示方法體
對比上面使用匿名函數創建委托實例,左邊的p就相當於 numb,右邊的p+10就相當於{return p+10;}
我們可以樂觀的認為,lambda表達式在編譯階段仍然轉換成了對應的匿名函數,別問我怎么知道,我猜的!
畫張圖表示一下。
所以我們前面說過,lambda表達式也是匿名函數,只不過簡化了匿名函數的使用。
所以我們前面也說,lambda表達式是用來創建委托的,你看我們剛才不就是再創建委托的實例嗎?!
所以到現在為止,你應該記住一句話:lamb表達式沒什么特殊之處,只不過是C#的一種語言特性而已,或者說一種語法而已。
道理明白了,下面我們來稍微加強一點。
定義一個兩個參數的委托
delegate int del(int arg1,int arg2);
自己試試,首先使用匿名函數的方式創建這個委托的一個實例,然后再使用lambda表達式看看。
使用匿名函數
del d1 = delegate(int numb1, int numb2) { return numb1 + numb2; }; Console.WriteLine(d1(10,10)); Console.ReadKey();
使用lambda表達式
del d1 = (p, z) => p + z; Console.WriteLine(d1(10,10)); Console.ReadKey();
沒錯,兩個參數的時候就是使用括號括起來,用都好分割兩個參數,這里p就表示numb1,z就表示numb2。
我們稍微弄個復雜點的:定義一個購物的委托
/// <summary> /// 定義一個購物的委托,分別接受兩個參數 /// </summary> /// <param name="spend">實際消費金額</param> /// <param name="cash">付給商家的金額</param> /// <returns>商家找回的金額</returns> delegate double ShoppingDelegate(double spend, double cash);
使用匿名方法的方式創建這個委托的實例,方法的邏輯稍微復雜點
ShoppingDelegate d1 = delegate(double spend, double cash) { /*變量card表示會員卡上的金額,我們都有經驗,如果經常會將幾毛錢存入會員卡,方便下次使用,這樣可以少帶零錢。如果會員卡的金額>0.5,則將會使用會員卡上的金額;否則不適用*/ double card = 0.5; if (card > 3) { return cash - spend + card; } else { return cash - spend; } };
這樣該如何改成lambda表達式呢?沒錯,如果代碼比較多的話,lambda表達式也使用{}。
ShoppingDelegate d1 = (p,z)=> { /*變量card表示會員卡上的金額,我們都有經驗,如果經常會將幾毛錢存入會員卡,方便下次使用,這樣可以少帶零錢。如果會員卡的金額>0.5,則將會使用會員卡上的金額;否則不適用*/ double card = 0.5; if (card > 3) { return z - p + card; } else { return z - p; } };
有人會問,為什么lambda表達式中的參數p和z不用spend和cash表示呢?當然可以了,只不過lambda表達式比較叼,能用一個字符表示的,絕對不使用一個半。
好,這一節就到這里,下一節專門說說lambda表達式和linq的配合使用。