c#之Lambda運算式

來源:互聯網
上載者:User

標籤:匿名類   sys   bsp   lin   double   方法   因此   ima   大寫   

Lambda運算式

前言:我們可以使用 一個新文法把實現的代碼賦予委託:Lambda運算式。只要有委託參數類型的地方就可以使用Lambda運算式。我們把我們上一篇部落格中的例子改為Lambda運算式。

完整的代碼如下:

 

 

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace _15匿名方法{    class Program    {        static void Main(string[] args)        {            string mid = ",我是中間的,";            Func<string, string> lambda = param =>          {              param += mid;              param += "我是最後的";              return param;          };            Console.WriteLine(lambda("我是最前面的"));            Console.ReadKey();        }    }}

代碼的顯示如下:

Lambda運算式有幾種定義參數的方式。“=>”的左邊列出了需要的參數,Lambda運算子的右邊定義了賦予Lambda變數的方法的實現的代碼。

一:參數:

Lambda運算式有幾種定義參數的方式,如果只有一個參數的話,唯寫出參數名就可以了。下面的Lambda運算式使用了參數s。因為委託定義了一個string參數,所以s的類型就是string類型。實現代碼調用String.Format();方法來返回一個字串,在調用該委託的時候,就把字串寫在控制台上。

Func<string, string> oneParam = s => string.Format("轉換為大寫的形式 :{0}", s.ToUpper());Console.WriteLine(oneParam("hao"));

如下:

如果使用多個參數的時候,就把參數名放在花括弧中,這裡參數x和y都是double類型,由Func<double,double,double>委託定義:

private static Func<double, double, double> _twoParams = (x, y) => x * y;

方法的調用:

Console.WriteLine(_twoParams(3, 2));

我們可以不在花括弧中添加參數的類型,因為編譯器會自動的協助我們匹配參數的類型。

二:多行代碼:

如果Lambda運算式中只有一條語句的話,在方法塊內就不需要花括弧和return語句,因為編譯器會添加一條隱式的return語句。比如我們看下面的一行代碼:

private static Func<double, double> squate = x => x * x;

但是添加或括弧和return語句也是完全合法的,但是添加這些符號不容易閱讀,添加之後如下:

private static Func<double, double> squate = x => { return x * x; };

但是在Lambda運算式中如果想實現多條語句的時候,就必須加上花括弧和return;

           Func<string, string> anonDel = param =>            {                param += mid;                param += "and this was added to the string";                return param;            };

三:閉包:

通過Lambda運算式可以訪問Lambda運算式外部的變數。這稱為閉包. 閉包是一個非常好的功能,但是如果使用不當的話,也會非常的危險,我們首先看一個例子:

 

int someVal = 5;Func<int, int> f = x => x + someVal;

 

 

假設不假設在調用f時,Lambda運算式建立了一個以後使用的新方法,這似乎沒有什麼問題,我們看看我們上面寫的代碼,調用f的傳回值應該是x+5的結果。但似乎不是這樣,假定我們要修改someVal,於是調用Lambda運算式時,會使用someVal的新值。調用f(3)的結果是10;

特別是,當通過另一個線程調用Lambda運算式的時候,我們可能不知道進行了這個調用,也不知道外部的變數的當前值是什嗎?那我們Lambda運算式在訪問外部的變數的時候,對於Lambda :x=>x + someVal ,編譯器會建立一個匿名類,它有一個建構函式來傳遞外部的變數。該建構函式取決於從外部傳遞進來的變數個數。對於這個簡單的例子。建構函式會接收一個int。匿名類包含一個匿名的方法。完整的代碼如下:

 

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace _16Lambda運算式{    /// <summary>    /// 匿名類    /// </summary>    public class AnonymousClass    {        private int _someVal;        public int SomeVal        {            get { return _someVal; }            set { _someVal = value; }        }        /// <summary>        /// 建構函式初始化賦值操作        /// </summary>        /// <param name="someVal">外部傳遞的值</param>        public AnonymousClass(int someVal)        {            this.SomeVal = someVal;        }        /// <summary>        /// 匿名方法        /// </summary>        /// <param name="x"></param>        /// <returns></returns>        public int AnonymousMathod(int x)        {            return x + _someVal;        }    }}

使用Lambda運算式並調用該方法,會建立一個匿名類的執行個體,並傳遞調用該方法時的變數。

四:使用foreach語句的閉包:

我們先看代碼:

using System;using System.Collections.Generic;using System.Linq;using System.Security.Cryptography.X509Certificates;using System.Text;using System.Threading.Tasks;namespace _16Lambda運算式{    class Program    {        static void Main(string[] args)        {            //泛型集合            List<int> values = new List<int>() { 10, 20, 30 };            //泛型集合中儲存一個委託類型的方法(有傳回值無參數)            List<Func<int>> funcs = new List<Func<int>>();            //遍曆values儲存到集合中            //在集合中添加的對象是沒有參數的但是返回values集合中的每一個值            foreach (var val in values)            {                funcs.Add(() => val);            }            //遍曆集合刪除所有的方法  f():無參數有一個int類型的值            foreach (var f in funcs)            {                Console.WriteLine(f());            }            Console.ReadKey();        }    }}

在上面的例子中,首先用10 20 30 填充了一個名為values的列表,變數funcs引用了一個泛型列表,其中的每一個對象都引用Func<int>類型的委託。第一條foreach語句添加了funcs列表中的每一個元素。添加到項中的函數使用Lambda運算式定義。該Lambda運算式使用了一個變數val,該變數在Lambda運算式的外部定義為foreach語句的迴圈變數。第二條foreach語句迭代func列表,已調用列表中引用的每個函數。結果如下:

在c#5.0中,這段代碼發生了變化,但是使用c#4或者是更早的版本的時候,會在控制台中輸出3次30,在第一個foreach迴圈中國使用閉包時,所建立的函數是在調用,而不是在迭代是獲得val的值。編譯器會從foreach語中建立一個while迴圈。在c#4中,編譯器在while迴圈外部定義迴圈變數。在每次迭代是重用這個變數。因此,在迴圈結束的時候,該變數的值就是最後一次迭代的值。要想在使用c#4時,讓代碼的結果為10 20 30,必須將代碼改為使用一個局部的變數。並將這個局部的變數傳入Lambda運算式。這樣的話,每次迭代的值將保留一個不同的值。完整的代碼如下:

using System;using System.Collections.Generic;using System.Linq;using System.Security.Cryptography.X509Certificates;using System.Text;using System.Threading.Tasks;namespace _16Lambda運算式{    class Program    {        static void Main(string[] args)        {            //泛型集合            List<int> values = new List<int>() { 10, 20, 30 };            //泛型集合中儲存一個委託類型的方法(有傳回值無參數)            List<Func<int>> funcs = new List<Func<int>>();            //遍曆values儲存到集合中            //在集合中添加的對象是沒有參數的但是返回values集合中的每一個值            foreach (var val in values)            {                var v = val;                funcs.Add(() => v);            }            //遍曆集合刪除所有的方法  f():無參數有一個int類型            foreach (var f in funcs)            {                Console.WriteLine(f());            }            Console.ReadKey();        }    }}

在c#5.0中,不在需要做這種代碼的修改了(即將代碼修改為局部的變數)。在c#5.0會在while迴圈的代碼塊中建立一個不同的局部迴圈變數。所以值會自動的得到儲存。這是c#4.0和c#5.0的區別,是我們必須要知道的。

 

 

c#之Lambda運算式

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.