Lambda表達式詳細總結

(一)輸入參數

在Lambda表達式中,輸入參數是Lambda運算符的左邊部分。它包含參數的數量可以爲0、1或者多個。只有當輸入參數爲1時,Lambda表達式左邊的一對小括弧纔可以省略。輸入參數的數量大於或者等於2時,Lambda表達式左邊的一對小括弧中的多個參數質檢使用逗號(,)分割。

示例1

下面創建一個Lambda表達式,它的輸入參數的數量爲0.該表達式將顯示“This is a Lambda expression”字符串。


[csharp] view plain copy 

()=>Console.WriteLine("This is a Lambda expression.");  


分析2


由於上述Lambda表達式的輸入參數的數量爲0,因此,該Lambda表達式的左邊部分的一對小括弧不能被省略。


示例2

下面創建一個Lambda表達式,它的輸入參數包含一個參數:m。該表達式將計算m參數與2的乘積。

[csharp] view plain copy 

m=>m*2;  


分析2


上述Lambda表達式的輸入參數省略了一對小括弧,它與“(m)=>m*2”Lambda表達式是等效的。


示例3

下面創建一個Lambda表達式,它的輸入參數包含兩個參數:m和n。該表達式將計算m和n參數的乘積。

[csharp] view plain copy 

(m,n)=>m*n;  




(二)表達式或語句塊


多個Lambda表達式可以構成Lambda語句塊。語句塊可以放到運算符的右邊,作爲Lambda的主體。根據主題不同,Lambda表達式可以分爲表達式Lambda和語句Lambda。語句塊中可以包含多條語句,並且可以包含循環、方法調用和if語句等。


示例1

下面創建一個Lambda表達式,它的右邊部分是一個表達式。該表達式計算m參數的平方值。

[csharp] view plain copy 

m=>m*n;  


分析1


如果Lambda表達式的右邊部分是一個語句塊,那麼該語句塊必須被"{"和"}"包圍。


示例2

下面創建一個Lambda表達式,它的輸入參數包括兩個參數:m和n。該表達式的右邊包含2個表達式;第一個表達式計算m和n參數的乘積,結果保存爲result變量;第二個表達式顯示result變量的值。

[csharp] view plain copy 

(m,n)=>{int result=m*n; Console.WriteLine(result);}  


分析2


上述Lambda表達式的右邊部分包含2個表達式,因此,該表達式的右邊部分必須被"{"和"}"包圍。



(三)查詢表達式

查詢表達式是一種使用查詢語法表示的表達式,它用於查詢和轉換來自任意支持LINQ的數據源中的數據。查詢表達式使用許多常見的C#語言構造,易讀簡潔,容易掌握。它由一組類似於SQL或XQuery的聲明性語法編寫的子句組成。每一個子句可以包含一個或多個C#表達式。這些C#表達式本身也可能是查詢表達式或包含查詢表達式。

●查詢表達式必須以from子句開頭,以select或group子句結束。第一個from子句和最後一個select子句或group子句之間,可以包含一個活多個where子句、let子句、join子   句、orderby子句和group子句,甚至還可以是from子句。它包括8個基本子句,具體說明如下所示。

●from子句:指定查詢操作的數據源和範圍變量。

●select子句:指定查詢結果的類型和表現形式。

●where子句:指定篩選元素的邏輯條件。

●let子句:引入用來臨時保存查詢表達式中的字表達式結果的範圍變量。

●orderby子句:對查詢結果進行排序操作,包括升序和降序。

●group子句:對查詢結果進行分組。

●into子句:提供一個臨時標識符。join子句、group子句或select子句可以通過該標識符引用查詢操作中的中堅結果。

●join子句:連接多個用於查詢操作的數據源。


示例1

下面創建一個查詢表達式query,該查詢表達式查詢arr數組中的每一個元素。

int[]arr =new int[]{0,1,2,3,4,5,6,7,8,9};


分析1

[csharp] view plain copy 

var query1=from n in arr  

                select n;  



示例2

下面創建一個查詢表達式query2.該查詢表達式查詢arr數組中大於6的元素。

[csharp] view plain copy 

int[] arr =new int[]{0,1,2,3,4,5,6,7,8,9};  

var query2=from n in arr  

              where n >6  

              select n;  


分析2

變量只是保存查詢操作,而不是查詢的結果。當查詢表達式執行查詢操作時,纔會計算該查詢表達式的結果。以上兩個變量的類型都屬於集合類型。


(四)from子句

from子句用來指定查詢表達式的數據源和範圍變量。它是查詢表達式的必有部分,並且它出現在最開始。數據源不但可以包括查詢本身的數據源,而且還可以包括子查詢的數據源。範圍變量用來表示數據源序列中的每一個元素。

注意:from子句指定的數據源的類型必須爲IEnumerable,IEnumerable<T>或一種派生類型。


示例1

下面創建一個查詢表達式query。該查詢表達式查詢arr數組中的每一個元素。在query查詢表達式中,arr數組爲數據源,n爲範圍變量。n範圍變量的類型arr數據源的元素類型。


分析1

[csharp] view plain copy 

int[] arr =new int[] {0,1,2,3,4,5,67,8,9};  

var query =from n in arr  

 select n;  


下面我們來學習數據源和包含不同的from子句查詢表達式。


數據源:指定數據的來源,它的形式可以爲靜態數組、動態數組(Arraylist)、集合、數據集(DataSet)、數據表、MML片段、MML文件等。

如果數據源實現了IEnumerable<T>接口,那麼編譯器可以推斷範圍變量的類型爲其元素類型。例如:數據源的類型爲IEnumerable<UserInfo>,那麼可以推斷出範圍 變量的類型爲UseInfo。


示例2

下面創建一個查詢表達式query。該查詢表達式查詢list反省數組中的每一個元素。在query查詢表達式中,list反省數組爲數據源。u爲範圍變量。u範圍變量的類型爲list數據源的元素類型(UserInfo)。


分析2

[csharp] view plain copy 

List<UserInfo> list=...  

var query =from u in list  

           select u;  


如果當數據源是非泛型IEnumerable類型(如ArrayList等)時,需要顯示指定範圍變量的類型。



示例3

下面創建一個查詢表達式query。該查詢表達式查詢list數組中的每一個元素。在query查詢表達式中,list數組爲數據源,u爲範圍變量。u範圍變量的類型被指定爲list數據源的元素類型(UserInfo)。


分析3

[csharp] view plain copy 

ArrayList list =new ArrayList();  

list.Add(...);  

...  

var query =from UserInfo u in list  

    select u;  




包含單個from子句的查詢表達式

在查詢表達式中,from子句至少有一個。當from子句只有一個時,構成的查詢表達式被稱爲包含單個from子句的查詢表達式。一般的,包含單個from子句的查詢表達式只包含一個數據源。


示例4

下面創建一個查詢表達式query。該查詢表達式查詢arr數組中的每一個元素,它就是一個包含單個from子句的查詢表達式。


分析4

[csharp] view plain copy 

int[] arr =new int[]{0,1,12,3,4,5,6,7,8,9};  

var query =from n in arr  

       select n;  


包含多個from子句的查詢表達式


在查詢表達式中,當from子句有兩個或兩個以上時,構成的查詢表達式被稱爲包含多個from子句的查詢表達式。


示例5

下面創建一個查詢表達式query。該查詢表達式包含兩個from子句,他們分別查詢兩個獨立的數據源;arr1數組和arr2數組。最後,使用select子句計算當前元素的和。

分析5

[csharp] view plain copy 

int[] arr1= new int[] {0,1,2,3,4,5,6,7,8,9};  

int[] arr2=new int[] {0,1,2,3,4,5,6,7,8,9};  

var query =from a in arr1  

       from b in arr2  

       select a +b;  


包含符合from子句的查詢表達式


在查詢表達式中,有可能查詢表達式的數據源中的每一個元素本身也作爲該查詢表達式的數據源。那麼要查詢數據源中的每一個元素中的元素,則需要使用符合from子句。符合from子句類似於嵌套的foreach語句。


示例6

下面創建一個名稱爲Test的類,該類包含兩個字段:Name和AliasName。其中,Name字段的類型爲string,AliasName字段的類型爲string類型列表。因此,它也可以作爲子查詢表達式的數據源。


分析6

[csharp] view plain copy 

public class Test  

{  

    Public string Name;  

    Public List<string> AliasName;  

}  



示例7

下面創建一個查詢表達式query。該查詢表達式包含了一個符合from子句:第一個from子句查詢list泛型集合;第二個from子句查詢list集合中元素的AliasName字段,爲第一個from子句的子查詢。最後,使用select子句將u變量的Name屬性的值和name變量的值拼接爲一個字符串。


分析7

[csharp] view plain copy 

List<MUserInfo> list =...  

var query =from u in list  

     from name in u.AliasName  

select u.Name+name;  




(五)select子句


select子句用來指定將在執行查詢時產生的值的類型。查詢表達式必須以select子句或group子句結束。


示例1

下面創建一個查詢表達式query。該查詢表達式查詢arr數組中的每一個元素。


分析1


[csharp] view plain copy 

int[] arr =new int[] {0,1,2,3,4,5,6,7,8,9};  

var query =from n in arr  

       select n;  


示例2


下面創建一個查詢表達式query。該查詢表達式查詢arr數組中的每一個元素和10的乘積。



[csharp] view plain copy 

int[] arr =new int[] {0,1,2,3,4,5,6,7,8,9};  

var query =from n in arr   

    select n*10;  


分析2


select子句中的“n*10”表達式決定了查詢結果的表現形式,即計算每一個元素和10的乘積。


示例3

下面創建一個查詢表達式query。該查詢表達式查詢arr數組中的每一個元素,查詢結果是一個對象的集合對象包含兩個屬性:ID和Name,它在select子句中由匿名對象初始化器創建。每一個對象的ID屬性的值是當前元素的值、Name屬性的值爲元素的值的字符串的表現形式。


分析3


[csharp] view plain copy 

int[] arr =new int[]{0,1,2,3,4,5,6,7,8,9};  

var query =from n in arr   

    select new  

    {  

         ID=n,  

         Name =n.ToString()  

    };  




(六)where子句


where子句用來指導將在查詢表達式中返回數據源中的哪些元素。它將一個布爾條件應用於數據源中的每個元素,並返回指定條件的元素。查詢表達式可以包含一個或多個where子句。


示例1

下面創建一個查詢表達式query。該查詢表達式從arr數組中查詢小於3的元素

[csharp] view plain copy 

int[] arr =new int[] {0,1,2,3,4,5,6,7,8,9};  

var query =from n in arr  

        where n <3  

        select n;  


分析1


上述where子句只包含一個布爾表達式“n<3”,該表達式將篩選小於3的元素。


在一個where子句中,也可以包含多個布爾表達式,各個表達式直接使用邏輯運算符(如&&和||)分隔。


示例2

下面創建一個查詢表達式query。該查詢表達式從arr數組中查詢大於3且小於6的元素。


[csharp] view plain copy 

int[] arr =new int[]{0,1,2,3,4,5,6,7,8,9};  

var query =from n in arr  

              where n >3 && n<6  

              select n;  


分析2


上述where子句包含兩個布爾表達式"n>3"和"n<6",它們共同指定將篩選大於3且小於6的元素。這兩個布爾表達式使用&&運算符鏈接,即計算這兩個布爾表達式的邏輯與。


where子句不但可以包含布爾表達式,而且還可以包含返回布爾值的方法。


示例3

下面創建一個查詢表達式query.該查詢表達式從arr數組中查詢爲偶數的元素。

[csharp] view plain copy 

int[] arr =new int[]{0,1,2,3,4,5,6,7,8,9};  

private bool IsEven(int i)  

{  

    return i%2==0?true:false;  

}  

var query =from n in arr  

              wehre IsEven(n)  

              select n;  


分析3


上述where子句包含一個返回布爾值的方法"IsEven(int i)"。該方法判定元素是否爲偶數。如果是,則返回true,否則返回false。


(七)let子句


let子句用來創建一個新的範圍變量,它用於存儲子表達式的結果。let子句使用編程者提供的表達式的結果初始化該變量。一旦初始化了該範圍變量的值,它就不能用於存儲其他的值。


示例1

下面創建一個查詢表達式query。該查詢表達式從arr數組中查詢爲偶數的元素。

[csharp] view plain copy 

int[] arr =new int[]{0,1,2,3,4,5,6,7,8,9};  

var query =from n in arr  

        let isEven =return n%2==0?true:false;  

        where isEven   

        select n;  


分析1


"return n%2==0?true:false"表達式判斷n元素是否爲偶數。如果是,則返回true,否則返回false。“let isEven =return n%2==0?true:false”表達式使用let子句創建新的範圍變量isEven,用來保存"return n%2==0?true:false"表達式的結果。"where isEven"表達式使用where子句篩選isEven的值爲true的元素。


(八)orderby子句


orderby子句可使返回的查詢結果按升序或者降序排序。升序由關鍵字ascending指定,而降序由關鍵字descending指定。

注意:orderby子句默認排序方式爲升序。


示例1

下面創建一個查詢表達式query。該查詢表達式從arr數組中查詢大於1且小於6的元素,並且按照n元素對查詢結果進行降序排序。

[csharp] view plain copy 

int[] arr =new int[]{0,1,2,3,4,5,6,7,8,9};  

var query =from n in arr  

        where n>1 && n<6  

        orderby n descending  

        select n ;  



分析1

orderby子句可以包含一個或多個排序表達式,各個排序表達式使用逗號(,)分隔。


示例2

下面創建一個查詢表達式query。該查詢表達式從arr數組中查詢大於1且小於6的元素。它使用orderby子句對查詢結果進行排序,且包含兩個排序關鍵字,具體說明如下所示:n%2:按照升序排序;n:按照降序排序。

注意:n%2排序關鍵字優先級大於n排序關鍵字。因此,該查詢表達式的結果首先按照n%2排序關鍵字升序排序,然後在按照n排序關鍵字降序排序。


分析2

在"orderby n%2 ascending,n descending"表達式中,第一個排序關鍵字後的"ascending"可以省略。因爲默認排序方式爲升序。


(九)group子句


group子句用來將查詢結果分組,並返回一對象序列。這些對象包含零個或更多個與改組的key值匹配的項,還可以使用group子句結束查詢表達式。

注意:每一個分組都不是單個元素,而是一個序列(也屬於集合)。


示例1

下面創建一個查詢表達式query。該查詢表達式從arr數組中查詢大於1且小於6的元素,並且按照n%2表達式的值對查詢結果進行分組。

[csharp] view plain copy 

int[] arr =new int[]{0,1,2,3,4,5,6,7,8,9};  

var query =from n in arr  

        where n>1 && n<6  

        group n by n%2;  


分析1


query查詢表達式的結果是一個序列(類型爲IEnumerable<IGrouping<int,int>>),該序列的元素類型爲IGrouping<int,int>.其實,該查詢結果中的元素也是一個序列。


示例2

下面使用兩個foreach語句顯示query查詢表達式結果中每一個元素的值。

[csharp] view plain copy 

foreach(var g in query)  

{  

        foreach(var o in g)  

        {  

              Console.WriteLine(0);  

         }  

}  


分析2


使用group子句對查詢結果分組後,每一個分組都存在一個鍵(由key屬性表示)。通過key屬性可以獲取每一個分組的鍵的值。


(十)into子句 

into子句可以用來創建一個臨時標識符,將group、join或select子句的結果存儲到這個標識符中。


示例1

下面創建一個查詢表達式query。該查詢表達式從arr數組中查詢大於1且小於6的元素,並且按照n%2表達式的值對查詢結果進行分組。該查詢表達式的具體說明如下所示:

where n>1 && n<6:指定篩選大於1且小於6的元素。

group n by n%2 into g: 按照n%2表達式的值對查詢結果進行分組,並使用into子句創建臨時標識符g。該臨時標識符臨時保存分組結果。

from sn in g:從g標識符指定的每一個分組中查詢sn元素。

select sn:表示查詢sn元素。

[csharp] view plain copy 

int[] arr =new int[]{0,1,2,3,4,5,6,7,8,9};  

var query =from n in arr   

        where n>1&& n<6  

        group n by n%2 into g  

        from sn in g  

        select sn;  


分析1


上述查詢表達式的查詢結果包括4個元素,依次爲2、4、3和5


(十一)join子句


join子句用來連接兩個數據源,即設置兩個數據源之間的關係。join子句支持以下3種常見聯接方式。

內部聯接:元素的鏈接關係 必須同時滿足兩個數據源,類似於SQL語句中的inner join子句。

分組聯接:包含into子句的join子句。

左外部聯接:元素的鏈接關係必須滿足聯接中的左數據源,類似於SQL語句中的left join子句。


內部聯接:join子句的內部聯接要求兩個數據源都必須存在相同的值,即兩個數據源都必須存在滿足聯接關係的元素。

示例1

下面創建一個查詢表達式query。該查詢表達式使用join子句聯接了arra和arrb數組,具體說明如下。

創建arra數組,它包含10個元素(0~9)。

創建arrb數組,它包含5個元素(0、2、4、6和8)。

創建query查詢。

from a in arra:從arra數組中選擇元素,並表示爲a。

where a <7: 從arra數組中選擇小於7的元素

join b in arrb on a equals b: 將arra和arrb數組進行聯接,同時滿足a和b相等的條件。其中,b元素是arrb數組中的元素。

select a: 選擇a元素。

[csharp] view plain copy 

int[] arra =new int[] {0,1,2,3,4,5,6,7,8,9};  

int[] arrb =new int[]{0,2,4,6,8};  

var query =from a  in arra   

        where a <7  

        join b in arrb on a equals b   

        select a;  


分析1


上述查詢表達式首先選擇小於7的元素,(包括0~6),然後再喝arrb數組進行聯接,並獲取既包含在{0,1,2,3,4,5,6}集合中,又包含在arrb數組中的元素。最終,查詢表達式的結果包含4個元素(0、2、4和6)


分組聯接:join子句的分組聯接包含into子句的join子句的鏈接。它將左數據源與右數據源的元素一次匹配。左數據源的所有元素都出現在查詢結果中。若在右數據源中找到匹配項,則使用匹配的數據,否則用空表示。


示例1

下面創建一個查詢表達式query。該查詢表達式使用join子句聯接arra和arrb數組,具體說明如下:

創建arra數組,它包含10個元素(0~9)。

創建arrb數組,它包含5個元素(0、2、4、6和8)。

創建query查詢。

from a in arra:從arra數組彙總選擇元素,並表示爲a。

where a<7:從arra數組中選擇小於7的元素。

join b in arrb on a equals b into g:將arra和arrb數組進行聯接,同時滿足a和b相等的條件。最後,保存爲g分組。其中,b元素是arrb數組中的元素。

select new{ID=a,Values =g};指定查詢結果是一個對象集合。該對象包含兩個屬性:ID和Values,它在select子句中由匿名對象初始化器創建。每一個對象的ID屬性的值是當前元素的值、value屬性的值爲g分組。


左外部鏈接: join子句的左外部鏈接將返回左側數據源序列中的所有元素,就算它們在右側序列中沒有匹配的元素也是這樣。


示例2

下面創建一個查詢表達式query。該查詢表達式使用join子句聯接arra和arrb數組,具體說明如下所示:

創建arra數組,它包含10個元素(0~9)。

創建arrb數組,它包含5個元素(0、2、4、6和8)。

創建query查詢。

from a in arra:從arra數組中選擇元素,並表示爲a。

where a <7:從arra數組中選擇小於7的元素。

join b in arrb on a equals b into g:將arra和arrb數組進行聯接,同時滿足a和b相等的條件。最後,保存爲g分組。其中,b元素是arrb數組中的元素。


注意:在此,左數據源爲"from a in arrb"和"where a <7"產生的數據源,右數據源爲arrb數組。

from ab in g.DefaultEmpty():查詢g分組中的每一個元素。如果該分組不存在元素,則返回默認值。

如果序列(在此爲g)爲空,則DefaultEmpty() 方法返回只包含一個元素的序列,該元素類型的值爲默認值(在此爲0)。

select ab:選擇ab元素。


分析2

上述查詢表達式首先選擇小於7的元素(包括0~6),然後再和arrb數組進行左鏈接。該查詢表達式的結果包含7個元素(與左數據源中的元素的數量相等)。如果g分組爲空,則返回該分組的元素類型的默認值(0),否則返回該元素。當左數據源中的元素的值爲1、3和5時,g分組爲空,此時,它將返回默認值0.當左數據源中的元素的值爲0、2、4和6時,g分組不爲空。此時,它將返回該元素的值,分別爲0、2、4和6.最終,查詢表達式的結果包含7個元素(0、0、2、0、4、0和6)。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章