歡迎您光臨本站 註冊首頁

LINQ之路:查詢表達式

←手機掃碼閱讀     火星人 @ 2014-03-12 , reply:0
  

書寫LINQ查詢時又兩種語法可供選擇:方法語法(Fluent Syntax)和查詢表達式(Query Expression)。

LINQ方法語法的本質是通過擴展方法和Lambda表達式來創建查詢。C# 3.0對於LINQ表達式還引入了聲明式的查詢表達式,也叫查詢語法,通常來講,它是創建LINQ查詢的更加快捷的方式。儘管通過查詢語法寫出的查詢比較類似於SQL查詢,但實際上查詢表達式的產生並不是建立在SQL之上,而是建立在函數式編程語言如LISP和Haskell中的list comprehensions(列表解析)功能之上。本篇會對LINQ查詢語法進行詳細的介紹。

我們在前一篇LINAQ方法語法中所舉的示例:獲取所有包含字母”a”的姓名,按長度排序並將結果轉為大寫。下面是與之等價的查詢表達式語法:

  1. staticvoidMain(string[] args)  
  2. {  
  3. string[] names = { "Tom""Dick""Harry""Mary""Jay"};  
  4. IEnumerable<string>query =  
  5. from n innames  
  6. wheren.Contains("a"//Filter elements  
  7. orderby n //Sort elements  
  8. select n.ToUpper(); //Translate each element  
  9. foreach(stringname inquery)  
  10. Console.WriteLine(name);  

查詢表達式總是以from子句開始,以select或者group子句結束。From子句定義了查詢的範圍變數(range variable),可以認為該變數是對輸入sequence的一個遍歷,就像foreach做的那樣。下面這幅圖描述了查詢表達式的完整語法:

當然,.NET公共語言運行庫(CLR)並不具有查詢語法的概念。編譯器會在程序編譯時把查詢表達式轉換為方法語法,即對擴展方法的調用。這意味著,我們用查詢表達式寫出來的LINQ查詢都有等價的方法語法。對於上例中的查詢表達式,編譯器會轉換成下面的方法語法:

 

  1. IEnumerable<string>query = names  
  2. .Where (n => n.Contains("a"))  
  3. .OrderBy(n => n.Length)  
  4. .Select (n => n.ToUpper()); 

 

然後,應用編譯器對於方法語法的處理規則,上面的Where, OrderBy, Select查詢運算符會綁定到Enumerable類中的相應擴展方法。

範圍變數

範圍變數是緊隨from關鍵字之後定義的變數,一個範圍變數指向當前操作符所對應的輸入sequence中的當前元素。在我們的示例中,範圍變數出現在每一個查詢子句中,但要注意的是,變數實際是對不同sequence的遍歷,因為Where、OrderBy、Select會有不同的輸入sequence:

 

  1. IEnumerable<string>query =  
  2. from n innames //n是我們定義的範圍變數  
  3. wheren.Contains("a"//n直接來自names array  
  4. orderby n.Length //n來自filter之後的subsequent  
  5. select n.ToUpper(); //n來自OrderBy之後的subsequent 

 

當 編譯器把上面的查詢語法翻譯成方法語法后,我們會更清楚的看到範圍變數的這種行為:

 

  1. IEnumerable<string>query2 = names  
  2. .Where(n => n.Contains("a")) //n直接來自names array  
  3. .OrderBy(n => n.Length) //n來自filter之後的subsequent  
  4. .Select(n => n.ToUpper()); //n來自OrderBy之後的subsequent  

 

除了from關鍵字後面的範圍變數,查詢表達式還允許我們通過下面的子句引入新的範圍變數:

let

into

額外的from子句

稍後我們會在“LINQ中的子查詢、創建策略和數據轉換”一篇中討論他們的使用方法和適用場景。

查詢表達式和方法語法

查詢表達式和方法語法各有所長。對下面的場景來講,用查詢表達式寫出來得查詢會更加簡潔:

使用let關鍵字引入新的範圍變數

在SelectMany、Join或GroupJoin后引用外部範圍變數時

在簡單的使用Where、OrderyBy、Select時,兩種語法結構並沒有大的差別,此時可以根據你的喜好任意選擇。

對於只有單個查詢運算符組成的查詢,方法語法會更加簡短和易於理解。

最後,對於沒有對應查詢表達式關鍵字的查詢運算符,我們就只能選擇方法語法了。下面是存在對應查詢表達式關鍵字的運算符:Where、Select、SelectMany、OrderBy、ThenBy、OrderByDescending、ThenByDescending、GroupBy、Join、GroupJoin。

組合查詢語法

當一個查詢運算符沒有對應的查詢語法時,我們可以組合使用查詢語法和方法語法。唯一的約束是查詢中的每一個查詢語法部分必須是完整的,如以from開始以select或group結束。如下例:

 

  1. string[] names = { "Tom""Dick""Harry""Mary""Jay"};  
  2. //計算包含字母”a”的姓名總數  
  3. intmatches = (from n innames wheren.Contains("a") select n).Count(); //3//按字母順序排序的第一個名字  
  4. stringfirst = (from n innames orderby n select n).First(); //Dick 

 

這種組合語法通常在書寫更加複雜的查詢時會具有優勢,像上面這種簡單的查詢,我們只需要使用方法語法就能收到很好的效果:

  1. intmatches = names.Where(n => n.Contains("a")).Count(); //3  
  2. stringfirst = (names.OrderBy(n => n)).First(); //Dick 

原文鏈接:http://www.cnblogs.com/lifepoem/archive/2011/10/28/2227735.html



[火星人 ] LINQ之路:查詢表達式已經有669次圍觀

http://coctec.com/docs/program/show-post-71473.html