C#拉姆達(=>)表達式


前言:

之前小豬曾經分享過自己對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#高級編程(第七版)》

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM