C#2.0之前, 如果一個方法或者變量需要使用委托(delegate)時, 則之前必須創建一個命名方法, 並在需要委托的位置傳入這個名稱. 比如有一個針對int類型的數據處理, 目的是篩選出一個int數組中為奇數的元素, 或者其它一些滿足條件的元素...
00 public class Commom
01 {
02 //命名一個委托方法
03 public delegate bool IntFilter(int i);
04 //篩選出符合委托方法所要求的int, 返回一個int[]
05 public static int[] FilterArrayOfInts(int[] ints, IntFilter filter)
06 {
07 ArrayList aList = new ArrayList();
08 foreach (int i in ints)
09 if (filter(i))
10 aList.Add(i);
11 return (int[])aList.ToArray(typeof(int));
12 }
13 }
Commom類建立了一個統一的模型, 這個模型主要用於傳入一個delegate方法, 可以獲得這個delegate方法條件所要求的數字. 具體這個delegate方法可以寫在另一個類中, 可以寫很多方法, 檢測是否是奇數, 是否是偶數, 這個數是否是3的倍數...這個根據需要自己寫. 這樣寫可以提高Commom類的可重用程度.
00 //根據需要, 自己定義篩選方法
01 public class MyIntFilter
02 {
03 //自己定義的篩選方法1: 檢測是否是奇數
04 public static bool IsOdd(int i)
05 {
06 return ((i & 1) == 1);
07 }
08 //自己定義的篩選方法2: 檢測是否是偶數
09 public static bool IsEven(int i)
10 {
11 return ((i & 1) != 1);
12 }
13 //...根據需要還可以定義其它篩選方法
14 }
調用MyIntFilter中的篩選方法:
00 int[] nums = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
01 //篩選出奇數
02 int[] oddNums = Commom.FilterArrayOfInts(nums, MyIntFilter.IsOdd);
03 //篩選出偶數
04 int[] evenNums = Commom.FilterArrayOfInts(nums, MyIntFilter.IsEven);
05 //測試結果, 打印出oddNums和evenNums
06 Console.WriteLine("Print oddNums:");
07 foreach (int i in oddNums)
08 Console.Write(i + " ");
09 Console.WriteLine("Print evenNums:");
10 foreach (int i in evenNums)
11 Console.Write(i + " ");
使用"匿名方法"實現lambda的功能(Since C#2.0)
為什麼要使用匿名方法? 答: 偷懶. 為每一個篩選策略專門寫一個方法很多時候會令人很煩, 很多方法可能只被用到一次兩次, 且為每個方法都起一個好聽的名字並在調用這些方法的時候傳入這些方法名令人不爽, 因此C#2.0的時候可以使用"匿名方法"解決這一問題:
0 int[] nums = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
1 //篩選出奇數
2 int[] oddNums = Commom.FilterArrayOfInts(nums, delegate(int i)
3 {
4 return ((i & 1) == 1);
5 });
6 Console.WriteLine("Print oddNums:");
7 foreach (int i in oddNums)
8 Console.Write(i + " ");
這時篩選出了int數組中所有的奇數, 而沒有使用MyIntFilter類裡面用於判斷是否是奇數的方法. 這種匿名的方法好處在於省去了維護程序代碼中上下文的精力.
使用lambda表達式(Since C#3.0)
lambda表達式的形式如下:
0 (param1, param2, param3...)=>{doSomethingWithParam1, doSomethingWithParam2, doSomethingWithParam3...}
lambda的好處在於哪裡? 最關鍵的作用可能是可讀性提高了, 簡潔明了, 只需要列出方法體中需要使用到的參數, 然後加上=>{}, 在大括號中寫方法體. 但注意的是傳入的參數類型要滿足之前delegate定義的輸入類型, 並返回delegate定義的返回類型.
同樣是上面的要求, 從int數組中篩選出奇數, 使用lambda表達式就是這樣寫:
0 int[] nums = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
1 //篩選出奇數
2 int[] oddNums = Commom.FilterArrayOfInts(nums, (i) => ((i & 1) == 1));
3 foreach (int i in oddNums)
4 Console.Write(i + " ");
何時適合使用lambda表達式
比較三種做法, 可以發現lambda表達式最簡潔. 但並不是所有的這種情況都使用lambda表達式. 對於比較復雜的算法, 需要重用的算法, 最好還是使用第一種"命名方法", 因為這樣做, 在任何時候任何開發者都可以很方便的直接調用方法, 而不需考慮這些細節.
C#3.0很多新特性幾乎都暗示著是為Linq而服務的, Lambda表達式也不例外, 因為一個Linq查詢通常只需要調用一次, 不需要為每一個查詢專門命名一個方法.
作者:Create Chen