C#3.0新增功能09 LINQ 基礎07 LINQ 中的查詢語法和方法語法

介紹性的語言集成查詢 (LINQ) 文檔中的大多數查詢是使用 LINQ 聲明性查詢語法編寫的。可是在編譯代碼時,查詢語法必須轉換爲針對 .NET 公共語言運行時 (CLR) 的方法調用。 這些方法調用會調用標準查詢運算符(名稱爲 WhereSelectGroupByJoinMax 和 Average 等)。 能夠使用方法語法(而不查詢語法)來直接調用它們。html

查詢語法和方法語法在語義上是相同的,可是許多人發現查詢語法更簡單且更易於閱讀。某些查詢必須表示爲方法調用。 例如,必須使用方法調用表示檢索與指定條件匹配的元素數的查詢。 還必須對檢索源序列中具備最大值的元素的查詢使用方法調用。 System.Linq命名空間中的標準查詢運算符的參考文檔一般使用方法語法。 所以,即便在開始編寫 LINQ查詢時,熟悉如何在查詢和查詢表達式自己中使用方法語法也十分有用。express

標準查詢運算符擴展方法
下面的示例演示一個簡單查詢表達式 以及編寫爲基於方法的查詢 的語義上等效的查詢。
 1 class QueryVMethodSyntax
 2 {
 3     static void Main()
 4     {
 5         int[] numbers = { 5, 10, 8, 3, 6, 12};
 6 
 7         // 查詢語法
 8         IEnumerable<int> numQuery1 = 
 9             from num in numbers
10             where num % 2 == 0
11             orderby num
12             select num;
13 
14         // 方法語法
15         IEnumerable<int> numQuery2 = numbers.Where(num => num % 2 == 0).OrderBy(n => n);
16 
17         foreach (int i in numQuery1)
18         {
19             Console.Write(i + " ");
20         }
21         Console.WriteLine(System.Environment.NewLine);
22         foreach (int i in numQuery2)
23         {
24             Console.Write(i + " ");
25         }
26         
27         // Keep the console open in debug mode.
28         Console.WriteLine(System.Environment.NewLine);
29         Console.WriteLine("Press any key to exit");
30         Console.ReadKey();
31     }
32 }
33 /*
34     輸出:
35     6 8 10 12
36     6 8 10 12
37  */

這兩個示例的輸出是相同的。 能夠看到查詢變量的類型在兩種形式中是相同的:IEnumerable<T>api

爲了瞭解基於方法的查詢,咱們來仔細討論它。 在表達式右側,請注意,where 子句如今表示爲 numbers 對象上的實例方法,它具備類型 IEnumerable<int>(如同你會回憶起的那樣)。 若是熟悉泛型 IEnumerable<T> 接口,則會知道它沒有 Where 方法。 可是,若是在 Visual Studio IDE 中調用 IntelliSense 完成列表,則不只會看到 Where 方法,還會看到許多其餘方法(如 SelectSelectManyJoin 和 Orderby)。 這些都是標準查詢運算符。ide

顯示 Intellisense 中的全部標準查詢運算符的屏幕截圖。

雖然看起來彷佛 IEnumerable<T> 進行了從新定義以包括這些其餘方法,不過實際上狀況並不是如此。 標準查詢運算符做爲一種新類型的方法(稱爲擴展方法 )來實現。 擴展方法可「擴展」現有類型;它們能夠如同類型上的實例方法同樣進行調用。 標準查詢運算符擴展了 IEnumerable<T>,所以能夠寫入 numbers.Where(...)工具

若要開始使用 LINQ,你在擴展方法方面實際須要瞭解的全部內容是如何使用正確的 using指令將它們引入應用程序的範圍。 從應用程序的角度來看,擴展方法與常規實例方法是相同的。ui

有關擴展方法的詳細信息,請參閱擴展方法。 有關標準查詢運算符的詳細信息,請參閱標準查詢運算符概述 (C#)。 某些 LINQ 提供程序(如 LINQ to SQL 和 LINQ to XML),會實現本身的標準查詢運算符,併爲 IEnumerable<T> 以外的其餘類型實現額外的擴展方法。spa

Lambda 表達式

在上面的示例中,請注意,條件表達式 (num % 2 == 0) 做爲內聯參數傳遞給 Where 方法:Where(num => num % 2 == 0). 此內聯表達式稱爲 lambda 表達式。 可採用匿名方法、泛型委託或表達式樹的形式編寫本來必須以更繁瑣的形式編寫的代碼,這是一種便利的方式。在 C# 中,=> 是 lambda 運算符(讀爲「轉到」)。 運算符左側的 num 是輸入變量,它與查詢表達式中的 num 對應。 編譯器能夠推斷出 num 的類型,由於它知道 numbers 是泛型 IEnumerable<T> 類型。 Lambda 的主體與查詢語法中或任何其餘 C# 表達式或語句中的表達式徹底相同;它能夠包含方法調用和其餘複雜邏輯。 「返回值」就是表達式結果。debug

若要開始使用 LINQ,沒必要大量使用 lambda。 可是,某些查詢只能採用方法語法進行表示,而其中一些查詢須要 lambda 表達式。 進一步熟悉 lambda 以後,你會發現它們是 LINQ 工具箱中一種強大而靈活的工具。 有關詳細信息,請參閱 Lambda 表達式code

查詢的可組合性
在前面的代碼示例中,請注意,OrderBy 方法經過對 Where 調用使用點運算符來調用。Where 會生成通過篩選的序列,而後 Orderby 經過進行排序來對該序列進行操做。 因爲查詢返回 IEnumerable,所以可經過將方法調用連接在一塊兒在方法語法中撰寫查詢。 這是當你使用查詢語法編寫查詢時,編譯器在幕後進行的工做。 由於查詢變量不存儲查詢的結果,因此能夠隨時修改它或將它用做新查詢的基礎(即便在執行過它以後)。
 
相關文章
相關標籤/搜索