C#語法之Linq查詢基礎一


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兩個類。

一、IEnummerable<T>和IQueryable<T>區別

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<>>表達式樹。

二、Linq基礎查詢

前面區分了兩個接口,但API是一樣的,查詢用法也是一樣,只是提高數據源的方式不一樣。所以先拋開不一樣的,求同存異嘛,下面主要是講一下一樣的部分。

上面是在百科上下的圖片,雖然我也沒看明白這個圖,但在下面的幾篇博客中我會把Linq查詢的基本用法都列舉出來,今天這篇博客只是對Linq做一簡單介紹。

1.方法語法、查詢語法

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

LINQ方法語法是非常靈活和重要的,我們在這里將描述使用鏈接查詢運算符的方式來創建復雜的查詢,方法語法的本質是通過擴展方法和Lambda表達式來創建查詢。C# 3.0對於LINQ表達式還引入了聲明式的查詢語法,通過查詢語法寫出的查詢比較類似於SQL查詢。本篇會對LINQ方法語法進行詳細的介紹。

當然,.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的倍數的數字,輸出是2、9、6,但當把b改為2時,再次輸出結果發現輸出的是2、4、6,這個例子主要說明Linq是延遲計算,和其他地方的懶加載是一樣的,聲明的時候並不會直接計算出來,而是等到用時在計算。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM