前言:
之前小豬曾經分享過自己對C#委托的一點理解 其實在使用委托的過程中我們會大量的使用拉姆達(=>)表達式
介紹:
"Lambda表達式"是一個匿名函數,是一種高效的類似於函數式編程的表達式,Lambda簡化了開發中需要編寫的代碼量。它可以包含表達式和語句,並且可用於創建委托或表達式目錄樹類型,支持帶有可綁定到委托或表達式樹的輸入參數的內聯表達式。所有Lambda表達式都使用Lambda運算符=>,該運算符讀作"goes to"。Lambda運算符的左邊是輸入參數(如果有),右邊是表達式或語句塊。Lambda表達式x => x * x讀作"x goes to x times x"。
自C#3.0開始,就可以使用這種代碼賦予委托。只要有委托參數類型的地方,就可以使用Lambda表達式。
ps:lambda表達式的語法比匿名方法簡單。如果所調用的方法有參數,且不需要參數,匿名方法的語法就比較簡單,因為這樣不需要提供參數。
namespace TimeBookMVC4.TEST { class Program { static void Main(string[] args) { string mid = ", middle part,"; Func<string, string> lambda = param => { param += mid; param += " and this was added to thes string."; return param; }; Console.WriteLine(lambda("Start of string")); } } }
lambda運算符"=>"的左邊列出了需要的參數,右邊定義了賦予lambda變量的方法的實現代碼。
參數
Lambda表達式有集中定義參數的方式。如果只有一個參數,只寫出參數名就足夠了。下面的Lambda表達式使用了參數s。因為委托類型頂了一個string參數,所以s的類型就是string。實現代碼調用Strign.Format()方法來返回一個字符串,在調用該委托時,就把字符串寫到控制台上:
Func<string, string> oneparam = s => String.Format( "change uppercase {0}",s.ToUpper()); Console.WriteLine(oneparam("test"));
如果委托使用多個參數,就把參數名放在花括號中。這里參數x和y的類型是double,由Func<double,double,double>委托定義:
Func<double, double, double> twoparam = (x, y) => x * y; Console.WriteLine(twoparam(3,2));
為了方便,可以在花括號中給變量名添加參數類型:
Func<double, double, double> twoparam = (double x,double y) => x * y; Console.WriteLine(twoparam(3,2));
多行代碼
如果Lambda表達式只有一條語句,在方法塊內就不需要花括號和return語句,因為編譯器會添加一條隱式的return語句。
Func<double, double> square = x => x * x;
添加花括號、return語句和分號是完全合法的,通常這比不添加這些括號更容易閱讀:
Func<double, double> square = x => { return x*x; }
但是,如果在Lambda表達式的實現代碼中需要多條語句,就必須添加花括號和return語句:
Func<string, string> lambda = param => { param += mid; param += " and this was added to thes string."; return param; };
Lambda表達式外部的變量
通過Lambda表達式可以訪問Lambda表達式塊外部的變量。這是一個非常好的功能,但如果未正確使用,也會非常危險。
在下面的示例中,Fun<int,int>類型的Lambda表達式需要一個int參數,返回一個int。該Lambda表達式的參數用變量x定義。實現代碼還訪問了Lambda表達式外部的變量someVal。只要不認為在調用f時,Lambda表達式創建了一個以后使用的新方法,這似乎么有什么問題。看看這個代碼塊,調用f的返回值應是x加5的結果,但似乎不是這樣:
int someVal = 5; Func<int, int> f = x => x + someVal;
假定以后要修改變量someVal,於是調用Lambda表達式時,會使用someVal的新值。調用f(3)的結果是10:
someVal =7;
Console.WriteLine(f(3));
特別是,通過另一個線程調用Lambda表達式時,我們可能不知道進行了這個調用,也不知道外部變量的當前值是什么。
現在我們也許會奇怪,如何在Lambda表達式的內部訪問Lambda表達式外部的變量。為了理解這一點,看看編譯器在定義Lambda表達式時做了什么。對於Lambda表達式x=>x+someVal,編譯器會創建一個匿名類,他有一個構造函數來傳遞外部變量。該構造函數取決於從外部傳遞進來的變量個數。對於這個簡單的例子,構造函數接收一個int。匿名類包涵一個匿名方法,其實現代碼、參數和返回類型有Lambda變大事定義:
public class AnonymousClass { private int someVal; public AnonymousClass(int someVal) { this.someVal = someVal; } public int AnonymousMethod(int x) { return x + someVal; } }
使用Lambda表達式並調用該方法,會創建匿名類的一個實例,並傳遞調用該方法時變量的值。
參考:《C#高級編程(第七版)》