[C# 3.0 入門] [第一章 Lambda表達式] 第五節:Lambda表達式的使用范例 & Lambda表達式的各種變體
Lambda表達式的使用范例
到現在為止的例子大多數,完全都是從文法上到功能上的說明,多數情況下不必使用Lambda表達式也能夠寫出來。最後,我還是來展示幾個有一定實用性的Lambda表達式的實例。
這裡是一個,輸入整形的數組,以其值為除數,執行除法運算後輸出結果的程序。因為要執行除法運算,所以輸入的值可能存在不能接受的值(0)的情況(就是說,這個示例代碼可以在輸入值不正確的情況下也能正常工作)。
那麼,這個程序的輸入如果是0的情況下,就提示信息然後必須退出。這個意圖如果用Lambda表達式該怎麼寫呢?
這個問題的要點有兩個。
l 在執行計算的循環中檢查0值的話,計算開始後會發生中斷。就是說,可能會同時計算值與錯誤信息兩者都輸出。
l 如果不輸出計算值只輸出錯誤信息的話,最好在計算的循環之前在設置一個檢查0值的循環。但是,這樣寫的話就用了兩個循環太冗長了。
總之,兩個方法都有缺點。換做筆者,如果有“計算開始前應該先檢查完畢”的要求,去除繁冗更重要,所以更願意選擇在循環內判定。
1using System;
2
3class Program
4{
5 static void Main(string[] args)
6 {
7 int[] a = { 1, 2, 0 };
8
9 foreach (int n in a)
10 {
11 if ( n == 0 )
12 {
13 Console.WriteLine("數組裡面含有0。");
14 return;
15 }
16 Console.WriteLine(100 / n);
17 }
18 // 輸出:
19 // 100
20 // 50
21 // 數組裡面含有0。
22 }
23}
24
25
List18 循環內判定的情況
然而,如果使用Lambda表達式,就會有一種完全不同的答案。要判斷所有數組的元素是否都滿足一定的條件,只需用一個調用一個方法的Lambda表達式,事情就有著落了。在不損失可讀性的范圍內,把Lambda表達式寫進if語句的條件中就能輕松的實現了。
實際寫出來的例子如下。Any方法是,集合的元素中只要含有一個滿足參數的Lambda表達式的元素就返回true。這個用到了.NET Framework的擴展方法,為了能夠使用,要在代碼前面加上“using System.Linq;”。
1using System;
2using System.Linq; // 為了使用Any方法
3
4class Program
5{
6 static void Main(string[] args)
7 {
8 int[] a = { 1, 2, 0 };
9
10 if (a.Any(x => x == 0))
11 {
12 Console.WriteLine("數組中含有0");
13 return;
14 }
15 foreach (int n in a) Console.WriteLine(100 / n);
16 }
17 // 輸出:數組中含有0。
18}
19
List19 使用Lambda表達式在計算之前就檢驗0值
如果是不能使用.Net Framework 3.5的場合,List19的if語句就要寫成下面的形式(稍稍有些冗長),這樣在.NET Framework 2.0下也同樣能夠使用。
if (Array.FindIndex(a, x => x == 0) >= 0)
這個例子,用Lambda表達式對集合數據的處理,感覺就像對單個值進行判斷的“if ( n == 0 )”一樣,對集合使用“if (a.Any(x => x == 0))”就能夠處理。
總之吧,使用循環的方法對集合元素進行判斷處理的方法,用僅僅一句if就能給替換了。如果經常使用這種技術,代碼的結構也會更明快簡潔。
【短評】“=>”是不等號?
BASIC系的語言中,不等號的寫法,“=”與“>”的順序沒有明確的規定。這樣的語言中,“>=”“=>”是等價的。正因為如此,熟悉了這樣的語言的話“=>運算符”就很容易會被誤認為是不等號。
例如如果有下面的Lambda表達式,如果是有上述語言的使用經驗的人看來,很容易就認為是不等號了。
x => 0
但是,使用Visual Basic的IDE的程序員,幾乎就不會看見作為不等號的“=>”。因為在IDE中輸入“=>”時,當場就會被自動替換為“>=”(Visual Basic 6.0與Visual Studio 2008會要求確認)
所以綜合起來考慮,如果是使用會把“=>”與不等號搞混的編程語言,那最好就要養成良好的編程習慣。
Lambda表達式的各種變體
Lambda表達式有各種變體。特別是在參數只有一個的情況下,因為在語法上可以省略參數兩邊的括弧,全面把握起來會比較困難。所以,下面的代碼給出幾種主流的變體的寫法。
1using System;
2
3delegate int NoArg();
4delegate int OneArg(int onlyOne);
5delegate int TowArgs(int first, int second);
6delegate void NoRetVal ();
7
8class Program
9{
10 static void Main(string[] args)
11 {
12 NoArg sample1 = () => 0;
13 OneArg sample2 = (x) => x * 2;
14 OneArg sample3 = (int x) => x * 2;
15 OneArg sample4 = x => x * 2;
16 TowArgs sample5 = (x, y) => x * y;
17 TowArgs sample6 = (int x, int y) => x * y;
18 OneArg sample7 = (x) => { return x * 2; };
19 OneArg sample8 = (int x) => { return x * 2; };
20 NoRetVal sample9 = () => Console.WriteLine("Hello!");
21 }
22}
23
List20 Lambda表達式的各種變體
sample1 = () => 0
在寫沒有參數的Lambda表達式的時候,要寫上沒有參數的空的括號。
sample2 = (x) => x * 2
有參數的情況下,用括號把參數表括上是最基本的寫法。
sample3 = (int x) => x * 2
當然,如果能夠明確指定參數的類型更好。
sample4 = x => x * 2
僅當參數只有一個的時候,參數兩邊的括弧可以省略。
sample5 = (x, y) => x * y
參數有多個的時候,用逗號分隔
sample6 = (int x, int y) => x * y
參數有多個的時候,也可以指定類型
sample7 = (x) => { return x * 2; }
Lambda語句的例子
sample8 = (int x) => { return x * 2; }
Lambda語中也可以指定類型
sample9 = () => Console.WriteLine("Hello!")
沒有返回值的情況,寫成調用void型返回值的方法的形式。
下期預告
介紹到這裡,Lambda表達式的大部分內容已經介紹過了。僅僅運用本章的知識,就能夠使代碼發生很大的質的變化了。
然而,如果說要完全理解了Lambda表達式的話,僅僅這樣的話還為時尚早。
實際上,推斷被省略了的類型聲明的“類型推斷”的麻煩事還在後頭呢。下一章,就來說說類型推斷。同時,也將會討論一下使用Lambda表達式的代理類型在類庫中的使用方法。例如,本章中的例子裡就用到了Action類型和Func類型。