(如下內容主要來自《C#本質論第三版》第十二章委託和Lambda表達式)數組
1、委託續函數
上上週五看了看委託,初步明白了其是個什麼,如何定義並調用。上週五準備看Lambda表達式,結果發現C#本質論中順帶講了講委託,因此在這,繼續寫一下委託。spa
首先,考慮以下問題:.net
須要對一個數組排序,先假設是數字,要求由大到小,很快咱們便想到了冒泡排序code
1 public static void bubblSort(int[] items) 2 { 3 int i, j, temp; 4 if (items == null) 5 { 6 throw new ArgumentNullException("錯誤"); 7 } 8 for (i = items.Length - 1; i >= 0; i--) 9 { 10 for (j = 1; j <= i; j++) 11 { 12 if (items[j - 1]<items[j]) 13 { 14 temp = items[j - 1]; 15 items[j - 1] = items[j]; 16 items[j] = temp; 17 } 18 } 19 } 20 }
顯然,能夠從大到小對數組進行排序,可是此時,咱們要求對數組從大到小或者從小到大選擇,也很簡單,多寫一個Switch就好了,以下:blog
1 public static void bubblSort(int[] items, string style ) 2 { 3 int i, j, temp; 4 if (items == null) 5 { 6 throw new ArgumentNullException("錯誤"); 7 } 8 for (i = items.Length - 1; i >= 0; i--) 9 { 10 for (j = 1; j <= i; j++) 11 { 12 switch(style) 13 { 14 case "big": 15 if (items[j - 1]<items[j]) 16 { 17 temp = items[j - 1]; 18 items[j - 1] = items[j]; 19 items[j] = temp; 20 } 21 break; 22 case "little": 23 if (tems[j - 1]<items[j]) 24 { 25 temp = items[j - 1]; 26 items[j - 1] = items[j]; 27 items[j] = temp; 28 } 29 } 30 } 31 } 32 }
如此,我要是傳入一串字符數組,而後按拼音排序呢,能夠繼續寫Case語句,可是很明顯,這樣下去代碼很臃腫。通過分析發現,關鍵就在於If語句裏面的那個條件,若是我能將這個條件做爲一個可變的就行了。排序
而具體判斷呢,我能夠寫成一個一個的函數,到時候把這個函數傳進來就好了,因而想到了委託,我能夠定義一個以下類型的委託:編譯器
public delegate bool ComparisonHandler(int first, int second);
這樣,經過控制什麼時候返回真,即可以選擇想要的排序類型了。string
例如控制由大到小排序的函數以下:it
public static bool LessTan(int first, int second)//將他傳入委託,那麼就是降序排序 { return first < second; }
BubbleSort函數改爲以下形式:
1 public static void bubblSort(int[] items, ComparisonHandler comparisonhandler) 2 { 3 int i, j, temp; 4 if (items == null) 5 { 6 throw new ArgumentNullException("comparisonhandler"); 7 } 8 for (i = items.Length - 1; i >= 0; i--) 9 { 10 for (j = 1; j <= i; j++) 11 { 12 if (comparisonhandler(items[j - 1], items[j]))//即判斷是大是小以及判斷規則,均有此委託指定,只要保證返回的bool類型符合規定便可 13 { 14 temp = items[j - 1]; 15 items[j - 1] = items[j]; 16 items[j] = temp; 17 } 18 } 19 } 20 }
能夠看出,BubbleSort函數第二個參數是剛纔定義的委託類型,那麼當作以下調用的時候:
bubblSort(items,LessTan);
if語句會根據LessTan函數的返回值判斷是否執行。當更改了LessTan函數體中的返回值的條件時(或者編寫新的判斷返回值的函數),即可以選擇不一樣的排序方式了。
注:.net2.0之後,委託做爲參數傳入能夠直接用相同簽名的函數做爲實參,而不須要實例化,實例化以下寫:
bubblSort(items,new ComparisonHanlder(LessTan));
如今已經不須要這種寫法。
2、匿名方法
咱們由上文可知,BubbleSort接受了一個委託類型(實參爲與委託有相同簽名的函數),其實能夠不寫一個函數,而將LessTan寫成以下形式:
//降序,我沒有用委託調用LessThan,而是使用了匿名方法,固然在有參可是功能裏不要參數的時候,能夠省略參數列表,可是不推薦。 bubblSort(items, delegate(int first, int second) { return first < second; });
直接定義委託類型(這樣說欠妥),而不寫出任何名字,直接寫參數列表與函數體,這樣也能夠傳入BubbleSort,這就是通常的匿名函數的寫法。
匿名函數的參數與返回值也要與其對應的委託類型一致。
固然,在一些狀況下能夠把參數省略:
//降序,我沒有用委託調用LessThan,而是使用了匿名方法,固然在有參可是功能裏不要參數的時候,能夠省略參數列表,可是不推薦。 bubblSort(items, delegate{ return Console.WriteLine("!!"));
這樣系統會自動匹配參數,可是特別不推薦這種寫法。
3、Lambda表達式
Lambda表達式是C#3.0引進的 比匿名方法更加簡潔的一種匿名函數語法,我能夠不寫Delegate了。可是要寫看起來高大上的=>了。
例如匿名函數改爲以下代碼:
//語句Lambda //還能夠用Lambda表達式書寫更加簡介的匿名函數 bubblSort(items, (int first, int second) => { return first < second; });
能夠這麼讀這句話:first與second用於返回比較結果。 這一組語句叫作 語句Lambda,傳入Delegate類型的委託形參中,注意,變量與返回值要一致。
Lambda甚至能夠容許省略參數類型,只要你確保編譯器可以推斷出來類型,因此以上語句能夠改寫以下:
//Lambda還能夠推斷類型,由於我定義的comparisonhandler的兩個參數是int類型,因此能夠再也不寫出類型,若是一個參數寫出了類型,剩下的也要都寫 bubblSort(items, (first, second) => { compareCount++; return first < second; });
注意,即便沒有參數,Lambda表達式的左側也要寫()
剛纔那種寫法帶大括號,屬於語句Lambda。表達式Lambda只有一個表達式,寫法以下:
//表達式Lambda寫法 bubblSort(items, (first, second) => first < second);//語句有大括號組成的語句塊,而表達式在右側只有一個表達式
還有,當在表達式中調用外部變量的時候,我我的感受他被在執行的時候看成了靜態變量,例如上上句的compareCount是在主函數中定義的一個int類型,在Lambda表達式中調用了,在匿名函數的委託被銷燬前,該外部變量將一直存在,因此會統計出實際的比較次數。