Understand Lambda Expressions in 3 minutes(翻譯)

周見智發表於2014-12-03

本文翻譯自CodeProject上的一篇簡單解釋Lambda表示式的文章,適合新手理解。譯文後面我補充了一點對Lambda表示式的說明。

1.什麼是Lambda表示式?

Lambda表示式是一種匿名方法,多數情況下用來在LINQ中快速建立委託。簡單地說,它代表一個沒有被定義過的方法,比如沒有訪問修飾符、沒有返回值宣告也沒有方法名稱。

2.我們為什麼需要Lambda表示式?(為什麼我們需要定義一個沒有方法名的方法?)

為了更方便。Lambda表示式允許你在呼叫方法的地方去定義該方法的實現。當一個方法非常簡短,並且它只會被使用到過一次時,使用Lambda表示式非常節省時間,因為這時候我們可以不用單獨地去定義這個方法。

優點:

  • 減少碼字。Lambda表示式不要求指定方法的修飾符、返回值型別以及方法名;
  • 方便程式碼閱讀。使用Lambda表示式後,被呼叫方法的具體實現就在呼叫處,因此不需要去其他地方到處找方法的具體定義。

Lambda表示式應該是短小的,不應該是複雜的程式碼,否則程式碼看起來比較亂,不易讀懂。

3.怎樣定義一個Lambda表示式?

Lambda表示式基本定義:引數列表 => 執行程式碼。(如 (a,b) => {return a+b;},譯者注)

簡單例子

 

  • n是輸入引數
  • n%2 == 1是執行程式碼

你可以將以上程式碼理解為:輸入一個名為n的引數給一個匿名方法,如果輸入引數是奇數,那麼匿名方法會返回true。

以上程式碼中,將Lambda表示式作為引數傳遞。

(3分鐘結束,譯者注)

 

譯者補充:

.NET中Lambda表示式的引入主要是為了在程式設計中增添“函數語言程式設計”的風格,Java8中也引進了Lambda表示式,可見函數語言程式設計已經越來越受歡迎。

嚴格意義上講(非實際),一個Lambda表示式應該必須具備輸入引數和返回值,也就是說,Lambda表示式的格式應該是這樣的:

(引數列表) =>{執行程式碼;返回值}

上面引數列表不能是空的,最後也必須有返回值。這樣規定是為了與“數學函式”的定義對應(有自變數,有因變數,並且每個輸入有且僅有一個輸出與之對應)。那麼為什麼.NET中的Lambda表示式允許我們的引數列表為空,並且可以沒有返回值呢?這個主要原因是.NET雖然引入了“函數語言程式設計”風格,但是並沒有拋棄原來指令式程式設計風格,也就是說,現在它是一種混合式程式設計風格。事實上,越來越多“命令式風格”的語言引入了“函式式風格”,最終都變為了混合式程式設計風格。有關函數語言程式設計、指令式程式設計、數學函式等概念,請參見我這篇部落格:

函數語言程式設計(一)認識“程式設計正規化”和“函式”

另外我再舉兩個例子說明Lambda表示式的作用:

1.在方法呼叫處定義方法的實現

1 int a = 1;
2 int b = 2;
3 int c = ((Func<int, int, int>)((arg1, arg2) => { return arg1 + arg2; }))(a, b); //現場定義現場呼叫
4 Console.WriteLine("c is " + c);
5 Console.Read();

如上程式碼中,我們並沒有單獨定義一個方法來計算兩個整數的和,而是在需要用到的時候現場使用Lambda表示式去定義。

注:(arg1,arg2)=>{rerurn arg1+arg2;}與(arg1,arg2)=>arg1+arg2的效果是一樣的,前者更為通用,當表示式中有多行程式碼時,必須使用花括號。

2.將程式碼塊以引數的形式進行傳遞

使用Lambda表示式時,我們可以快速建立委託,進而將建立的委託作為引數進行傳遞。

List<int> list1 = new List<int>{1,2,3};
List<int> list2 = list1.where(n=>n%2==0).toList();

如上程式碼中,我們將程式碼塊“n=>n%2==0”(可以比這更為複雜)作為引數傳遞給擴充套件方法List<T>.Where。實際上,這裡是通過Lambda表示式快速建立了一個委託。不僅僅是.NET中有這種寫法,具備函數語言程式設計風格的JavaScript中同樣有類似寫法:

$.ajax({
        type: "POST",
        url: "http://localhost:10647/ ",
        data: JSON.stringify(Customer),
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: function (data, status, jqXHR)
        {
            alert(data);
        },
        error: function (xhr)
        {
            alert(xhr.responseText);
        }
    });

如上程式碼中,給$.ajax方法的success和error傳遞的均是匿名函式(程式碼塊),如果$.ajax方法在C#中也存在,那麼引數列表中的success引數完全可以這樣寫:

success:(data,status,jqXHR)=>alert(data),

或者這樣寫:

success:delegate(type1 data,type2 status,type3 jqXHR)  //type1 type2 type3 為資料型別
    {
        alert(data);
    },

這裡,Lambda表示式與使用delegate關鍵字建立匿名方法的效果是一樣的。

3.委託、命名方法、匿名方法以及Lambda表示式的關係

網上對於這三者的比較比較多,其實後面三個都是建立委託的一種方式,只是一個比一個簡潔(這很符合技術發展,哦NO,:)不要再黑“語法糖”了)。如果把委託比作int,那麼命名方法、匿名方法以及Lambda表示式可以看作1、2以及3。它們就是這種關係。

 

相關文章