Linq作.Net開發的應該都用過,有些地方很複雜的邏輯用Linq很方便的解決。對於Linq to object、Linq to xml、Linq to sql、Linq to Entity(EF)均可以使用linq查詢。不知道你們有沒有想過爲何linq對這些均可以使用呢?統一的api適用這麼多。其實主要仍是IEnummerable<T>和IQueryable<T>兩個接口。可能有人會問爲何是兩個接口?這兩個接口有什麼區別或者聯繫呢?這又要引出來Enummerable、Queryable兩個類。sql
1、IEnummerable<T>和IQueryable<T>區別api
using System.Runtime.InteropServices; namespace System.Collections { // // 摘要: // 公開枚舉數,該枚舉數支持在非泛型集合上進行簡單迭代。 [ComVisible(true)] [Guid("496B0ABE-CDEE-11d3-88E8-00902754C43A")] public interface IEnumerable { // // 摘要: // 返回一個循環訪問集合的枚舉器。 // // 返回結果: // 可用於循環訪問集合的 System.Collections.IEnumerator 對象。 [DispId(-4)] IEnumerator GetEnumerator(); } }
using System.Collections; using System.Linq.Expressions; namespace System.Linq { // // 摘要: // 提供對未指定數據類型的特定數據源的查詢進行計算的功能。 public interface IQueryable : IEnumerable { // // 摘要: // 獲取在執行與 System.Linq.IQueryable 的此實例關聯的表達式目錄樹時返回的元素的類型。 // // 返回結果: // 一個 System.Type,表示在執行與之關聯的表達式目錄樹時返回的元素的類型。 Type ElementType { get; } // // 摘要: // 獲取與 System.Linq.IQueryable 的實例關聯的表達式目錄樹。 // // 返回結果: // 與 System.Linq.IQueryable 的此實例關聯的 System.Linq.Expressions.Expression。 Expression Expression { get; } // // 摘要: // 獲取與此數據源關聯的查詢提供程序。 // // 返回結果: // 與此數據源關聯的 System.Linq.IQueryProvider。 IQueryProvider Provider { get; } } }
看它們兩個的定義也能看出IQueryable繼承IEnumerable,那二者什麼區別呢?那咱們能夠看下兩個接口的擴展類Enumerable、Queryable。數組
這兩個類API相同,可是仔細看能夠發現參數類型不同,一個是Fuc<> 一個是Expression<Fuc<>>,其實Queryable是對Linq to sql、EF來使用的,雖然對外的api是同樣的,但實現的原理是不同的,一個是func<>lamdbs表達式,一個是Expression<Fuc<>>表達式樹。ide
2、Linq基礎查詢ui
前面區分了兩個接口,但API是同樣的,查詢用法也是同樣,只是提升數據源的方式不同。因此先拋開不同的,求同存異嘛,下面主要是講一下同樣的部分。spa
上面是在百科上下的圖片,雖然我也沒看明白這個圖,但在下面的幾篇博客中我會把Linq查詢的基本用法都列舉出來,今天這篇博客只是對Linq作一簡單介紹。code
1.方法語法、查詢語法xml
書寫LINQ查詢時又兩種語法可供選擇:方法語法(Fluent Syntax)和查詢語法(Query Expression)。對象
LINQ方法語法是很是靈活和重要的,咱們在這裏將描述使用連接查詢運算符的方式來建立複雜的查詢,方法語法的本質是經過擴展方法和Lambda表達式來建立查詢。C# 3.0對於LINQ表達式還引入了聲明式的查詢語法,經過查詢語法寫出的查詢比較相似於SQL查詢。本篇會對LINQ方法語法進行詳細的介紹。blog
固然,.NET公共語言運行庫(CLR)並不具備查詢語法的概念。因此,編譯器會在程序編譯時把查詢表達式轉換爲方法語法,即對擴展方法的調用。因此使用方法語法會讓咱們更加接近和了解LINQ的實現和本質,而且一些查詢只能表示爲方法調用,如檢索序列中的最大值、最小值元素的查詢,他們在查詢語法中就沒有對應的實現。但另外一方面,查詢語法一般會比較簡單和易讀。無論怎樣,這兩種語法和互相補充和兼容的,咱們能夠在一個查詢中混合使用方法語法和查詢語法。
好比直接.List.where(p=>XX)這種是方法語法, from p in list XXXX這種是查詢語法,查詢語法仍是轉換爲方法語法。
2.延遲計算
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace LinqDemo { class Program { static void Main(string[] args) { int[] a = new int[] { 1,3,5,7,9,11,2,4,6}; int b = 3; var result = from p in a where p % b == 0 select p; foreach (var m in result) { Console.WriteLine(m); } Console.WriteLine("-------------------------"); b = 2; foreach (var m in result) { Console.WriteLine(m); } Console.ReadLine(); } } }
上面代碼第一次是b=3,照數組a中3的倍數的數字,輸出是二、九、6,但當把b改成2時,再次輸出結果發現輸出的是二、四、6,這個例子主要說明Linq是延遲計算,和其餘地方的懶加載是同樣的,聲明的時候並不會直接計算出來,而是等到用時在計算。