1. 程式人生 > >C# => Lambda表示式理解

C# => Lambda表示式理解

本文參考網上的部落格和找到的資料加上個人理解編寫的,主要的程式碼借鑑:http://www.cnblogs.com/knowledgesea/p/3163725.html、百度百科

希望能夠幫助理解lambda表示式。

定義:"Lambda表示式"是一個匿名函式,是一種高效的類似於函數語言程式設計的表示式

好處:Lambda簡化了匿名委託的使用,減少開發中需要編寫的程式碼量 具體內容:它可以包含表示式和語句,並且可用於建立委託或表示式目錄樹型別,支援帶有可繫結到委託或表示式樹的輸入引數的內聯表示式。 寫法:所有Lambda表示式都使用Lambda運算子=>,該運算子讀作"goes to"。Lambda運算子的左邊是輸入引數(如果有),右邊是表示式或語句塊。Lambda表示式x => x * x讀作"x goes to x times x"。
接下來從例子中慢慢學習:
namespace LambdaLearn
{
    public class Person
    {
        public string Name { get; set; }
        public int Age  {  get;set; }    
    }
    class Program
    {

        public static List<Person> PersonsList()//方法返回Person類的List集合
        {
            List<Person> persons = new List<Person>();
            for (int i = 0; i < 7; i++)
            {
                Person p = new Person() { Name = i + "人物年齡", Age = 8 - i, };
                persons.Add(p);                
            }
            return persons;
        }

        static void Main(string[] args)
        {
            List<Person> persons0 = PersonsList();
            List<Person> persons1 = persons.Where(p => p.Age > 6).ToList();   //所有Age>6的Person的集合
            Person per = persons.SingleOrDefault(p => p.Age == 1);  //Age=1的單個people類
            List<Person> persons2 = persons.Where(p => p.Name.Contains("年齡")).ToList();   //所有Name包含年齡的Person的集合
        }
    }
}

從例一可以看出一點lambda表示式的簡單用法,接著往下看。 Lambda簡化了匿名委託的使用,我們可以看一看下面例子怎樣簡化的。如果委託與事件不是很懂請看:http://blog.csdn.net/u013236878/article/details/52243017 例二:用lambda表示式簡化委託 利用委託處理方法:
//委託  逛超市
        delegate int GuangChaoshi(int a);
        static void Main(string[] args)
        {
            GuangChaoshi gwl = JieZhang;
            Console.WriteLine(gwl(10) + "");   //列印20,委託的應用
            Console.ReadKey();
        }
        
        //結賬
        public static int JieZhang(int a)
        {
            return a + 10;
        }

利用lambda表示式處理方法:

//委託  逛超市
        delegate int GuangChaoshi(int a);
        static void Main(string[] args)
        {          
           // GuangChaoshi gwl = JieZhang;
            GuangChaoshi gwl = p => p + 10;
            Console.WriteLine(gwl(10) + "");   //列印20,表示式的應用
            Console.ReadKey();
        }

委託跟表示式的兩段程式碼,我們應該能明白了:其實表示式(p => p + 10;)中的 p 就代表委託方法中的引數,而表示式符號右邊的 p+10,就是委託方法中的返回結果。 再看一個稍微複雜一點的例子:
//委託  逛超市
        delegate int GuangChaoshi(int a,int b);
        static void Main(string[] args)
        {            
            GuangChaoshi gwl = (p,z) => z-(p + 10);
            Console.WriteLine(gwl(10,100) + "");   //列印80,z對應引數b,p對應引數a
            Console.ReadKey();
        }
[code]csharpcode:
/// <summary>
        /// 委託  逛超市
        /// </summary>
        /// <param name="a">花費</param>
        /// <param name="b">付錢</param>
        /// <returns>找零</returns>
        delegate int GuangChaoshi(int a,int b);
        static void Main(string[] args)
        {
            GuangChaoshi gwl = (p, z) =>
            {
                int zuidixiaofei = 10;
                if (p < zuidixiaofei)
                {
                    return 100;
                }
                else
                {
                    return z - p - 10;
                }
           
            };
            Console.WriteLine(gwl(10,100) + "");   //列印80,z對應引數b,p對應引數a
            Console.ReadKey();
        }

接下來看一下lambda的具體寫法形式:隱式表達即沒有指定引數型別(因為編譯器能夠根據上下文直接推斷引數的型別)
(x, y) => x * y              //多引數,隱式型別=>表示式  
x => x * 5                   //單引數,隱式型別=>表示式  
x => { return x * 5; }       //單引數,隱式型別=>語句塊  
(int x) => x * 5             //單引數,顯式型別=>表示式  
(int x) => { return x * 5; } //單引數,顯式型別=>語句塊  
() => Console.WriteLine()    //無引數 

看完以上內容,理解lambda表示式已經不會有太大問題了,接下來的內容稍微會深一點(至少我理解了很久Orz...)

簡單瞭解一下lambda背景:

Lambda 用在基於方法的 LINQ 查詢中,作為諸如 Where 和 Where 等標準查詢運算子方法的引數。

使用基於方法的語法在 Enumerable 類中呼叫 Where 方法時(像在 LINQ to Objects 和 LINQ to XML 中那樣),引數是委託型別 System..::.Func<(Of <(T, TResult>)>)。使用 Lambda 表示式建立委託最為方便。例如,當您在 System.Linq..::.Queryable 類中呼叫相同的方法時(像在 LINQ to SQL 中那樣),則引數型別是 System.Linq.Expressions..::.Expression<Func>,其中 Func 是包含至多五個輸入引數的任何 Func 委託。同樣,Lambda 表示式只是一種用於構造表示式目錄樹的非常簡練的方式。儘管事實上通過 Lambda 建立的物件的型別是不同的,但 Lambda 使得 Where 呼叫看起來類似。

背景這種想要深入研究的可以都瞭解一下,本文只是幫助瞭解lambda,這裡就不多說了。

下列規則適用於 Lambda 表示式中的變數範圍:

捕獲的變數將不會被作為垃圾回收,直至引用變數的委託超出範圍為止。

在外部方法中看不到 Lambda 表示式內引入的變數。

Lambda 表示式無法從封閉方法中直接捕獲 ref 或 out 引數。

Lambda 表示式中的返回語句不會導致封閉方法返回。

Lambda 表示式不能包含其目標位於所包含匿名函式主體外部或內部的 goto 語句、break 語句或 continue 語句。

Lambda表示式的本質是“匿名方法”,即當編譯我們的程式程式碼時,“編譯器”會自動將“Lambda表示式”轉換為“匿名方法”,如下例:

string[] names={"agen","balen","coure","apple"};
string[] findNameA=Array.FindAll<string>(names,delegate(string v){return v.StartsWith("a");});
string[] findNameB=Array.FindAll<string>(names,v=>v.StartsWith("a"));

上面中兩個FindAll方法的反編譯程式碼如下:
string[]findNameA=Array.FindAll<string>(names,delegate(stringv){returnv.StartsWith("a");});
string[]findNameB=Array.FindAll<string>(names,delegate(stringv){returnv.StartsWith("a");});

Lambda表示式的語法格式: 引數列表 => 語句或語句塊 其中“引數列”中可包含任意個引數(與委託對應),如果引數列中有0個或1個以上引數,則必須使用括號括住引數列,如下: () => Console.Write("0個引數") I => Console.Write("1個引數時引數列中可省略括號,值為:{0}",i) (x,y) => Console.Write("包含2個引數,值為:{0}*{1}",x,y) 而“語句或語句塊”中如果只有一條語句,則可以不用大括號括住否則必須使用,如下: I => Console.Write("只有一條語句") I => { Console.Write("使用大括號的表示式"); } //兩條語句時必須要大括號 I => { i++;Console.Write("兩條語句的情況"); } 如果“語句或語句塊”有返回值時,如果只有一條語句則可以不輸寫“return”語句,編譯器會自動處理,否則必須加上,如下示例: “Lambda表示式”是委託的實現方法,所以必須遵循以下規則: 1)“Lambda表示式”的引數數量必須和“委託”的引數數量相同; 2)如果“委託”的引數中包括有ref或out修飾符,則“Lambda表示式”的引數列中也必須包括有修飾符;