1. 程式人生 > 其它 >【寫給Cpp選手的C#教程】Lambda篇

【寫給Cpp選手的C#教程】Lambda篇

現在幾乎所有語言都有Lambda表示式了吧,這裡就簡單寫一些。

Lambda表示式的簡單使用

//Lambda表示式的格式如下
//(parameters) => expression-or-statement-block
class Program
{
    static int tempFunc(int x) { return x * x; }
    static void Main()
    {
        Func<int, int> id1 = tempFunc;
        
        //較為複雜的寫法,是一個語句塊
        Func<int, int> id2 =/*往後是Lambda表示式*/ (x) => { return x * x; };
        
        //更加抽象的寫法,一個表示式,第一個x對應引數,x*x的結果對應返回值
        Func<int, int> id3 =/*往後是Lambda表示式*/ x => x * x;
    }
}

對於外部變數的捕獲

class Program
{
    static void Main()
    {
        int temp = 4;
        Func<int> lambda = () => temp++;
        temp = 8;
        Console.WriteLine(lambda());
        Console.WriteLine(temp);
    }
}

如上例所見,我們可以得到以下結論:

①Lambda表示式可以使用函式內部的、表示式外部的變數。

Lambda表示式引用外部變數被稱為捕獲變數(這個好像是動名詞),捕獲變數的表示式稱為閉包。

②函式執行時會傳入外部變數當時的值,而不是外部變數被捕獲時的值。

按照這個例子來看,執行時temp的值是8而不是4,儘管temp是在值為4時被捕獲的。

③函式執行時可以修改外部變數的值。

比如執行lambda之後,temp的值就被改變了。

然後我們來看第二個例子:

    class Program
    {
        static Func<int> Natual()
        {
            int seed = 0;
            return () => seed++;
        }
        static void Main()
        {
            Func<int> natual = Natual();
            natual();	//seed = 0,函式返回後變成1
            natual();	//seed = 1,函式返回後變成2
        }
    }

④捕獲變數的生命週期會延伸到和委託的生命週期一致

體現在,seed在Natual的生命週期中,原先應當隨函式的結束而被銷燬,但現在它的生命週期延長到了和natual委託相同的長度。

據說,被捕獲的變數會被儲存到一個隱藏的類中去,因此它的生命週期變得不同。

Lambda表示式和匿名方法

匿名方法比Lambda表示式缺少了幾個特性:

匿名方法沒有隱式型別的引數;

匿名方法必須是一個語句塊,而不能是表示式;

匿名方法並沒有在賦值給Expression時將其編譯為表示式樹的能力(看不懂啦

public delegate int NumDele(int x);
class Program
{
    static void Main()
    {
        NumDele square = delegate (int x) { return x * x; };
        //相當於下面這句
        NumDele lambda1 = (x) => {return x* x; };
        //相當於下面這句
        NumDele lambda2 = x => x * x;
    }
}