2017年9月9日 星期六

lambda語法 C#

lambda語法 C#
取自
說明
原始碼下載
https://drive.google.com/file/d/0B4DvqhDoI_WObGJYZEJRVjZONm8/view?usp=sharing
簡單的說,Lambda就是一種委派的匿名方法,lambda是怎麼從委派演進而來的。接下來,我會用C# 1.0, C# 2.0, C# 3.0,在使用委派時,是如何簡化成最後的lambda。
前言
什麼是lambda?舉個例子來說:
這就叫lambda。這個lambda可以當做方法參數,或是塞給變數。
在說明之前,我想先把上面這類例子,抽象來看有哪一些元素,來組成lambda:
=>:一個『=』,接著一個『>』符號,通常『=>』稱為goes to。也就是把左邊的東西,goes to 右邊的東西。
=>的左邊:可以有(),也就是括號符號,也可以沒有。括號裡面,可以沒有東西(例如第3種例子),也可以有東西,且可以不只一個東西,例如第1種例子。
=>的右邊:可以有一段運算式,例如第1, 2, 3種例子。可以有一段{}括起來可執行的區塊,例如第4種例子。可以有回傳,也可以沒有回傳東西。
先知道可以依據=>,將lambda拆成三個部分,讓我們繼續看下去。
場景
媽媽要炒菜,給錢,買鹽。
  1. C# 1.0的情況
  1. 先定義委派的簽章,也就是21行宣告delegate的部份。
  2. 在Cooking中,宣告一個getSalt的變數,其型別為剛剛定義的委派型別GetSalt。
  3. 媽媽將買鹽的邏輯,委派給Joey的BuySalt()方法來處理。
  4. 執行getSalt變數,取得鹽巴。
可以看到,需要四個步驟,重點在於:一定要定義一個實際的方法,不管是不是在媽媽身上,或是在別的Class上。不管是不是執行個體方法,還是靜態方法。總之,一定要定義一個實體的方法且有方法名字。
  1. C# 2.0的情況
  1. 一樣先定義委派的簽章。
  2. 在C# 2.0中,不再一定需要某一個執行個體方法或靜態方法,來指定委派變數。而可以直接透過delegate(參數){委派執行內容}的方式,定義委派要執行的內容。
  3. 執行getSalt變數,取得鹽巴。
在C# 2.0,已經把原本四個步驟,簡化成三個。原因就在,委派的執行內容,不再一定需要依賴於某一個執行個體方法,或是靜態方法。而可以直接透過delegate關鍵字宣告。我們稱之為匿名方法
  1. C# 3.0的情況
一樣是三個步驟,但把匿名方法的部份更加簡化了。
  1. 不需要再透過delegate來宣告。
  2. 基本上不需要定義參數的型別,除非無法推斷。
  3. 只有一個參數時,參數不需要用小括號括起來。如果沒有參數,或兩個參數以上,則一定要用小括號刮起來。(一個參數時,也可以括
結論
重新整理前言中的三個element:
  1. =>,代表這是個匿名方法。可以想像成宣告為delegate的匿名方法。意義是goes to,也就是把=>左邊的參數,交給=>右邊的運算式或陳述式執行。
  2. =>左邊,代表匿名方法的參數。可以沒有參數,可以多個參數,用『,』隔開。參數的位置,即為委派方法簽章的對應參數位置。參數的命名,可以不與委派方法簽章上相同,就如同C# 1.0的例子。這個參數的命名,只是供匿名方法內部所使用
  3. =>右邊,代表匿名方法的內容。可以使用=>左邊的參數,也可以使用匿名方法外部的變數。(兩者生命週期不同)
方法內容,可以沒有回傳值,例如委派的方法簽章上是回傳void。也可以有回傳值,看方法簽章上定義為何,以這例子來說,回傳型別為Salt。
回傳型別也可以是泛型型別,那就是泛型委派。
簡單的說,Lambda,就是一種委派的匿名方法的簡化寫法。只要了解C# 1.0, C# 2.0到C# 3.0,委派在使用上的演進,自然在面對lambda上那堆奇怪的符號,奇怪的位置與宣告,奇怪的內容,就可以對照到原本的意義了。


最後,附上執行的例子:媽媽時代。
class Program
   {
       static void Main(string[] args)
       {
           //媽媽時代
           var momGeneration = new List<Mom> { new Mom_CSharp_1(), new Mom_CSharp_2(), new Mom_CSharp_3() };


           Console.WriteLine("用120元買的鹽炒菜");
           MomsCooking(momGeneration, 120);
           Console.WriteLine();


           Console.WriteLine("用80元買的鹽炒菜");
           MomsCooking(momGeneration, 80);
           Console.WriteLine();
       }


       private static void MomsCooking(List<Mom> momGeneration, int money)
       {
           foreach (var mom in momGeneration)
           {
               mom.Cooking(money);
           }
       }
   }
結果:

補充:通常在設計委派,我們定義完委派的方法簽章後,會在class上宣告一個public的變數,或是在方法的參數上,來使用這個委派的型別。而此變數或參數,實際所要執行的方法內容,會交由外部來決定。這樣子設計,才會有彈性。在Mom的類別中,才不需要去考慮,究竟鹽巴是怎麼買回來的。

沒有留言:

張貼留言