国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

.Net如何實現LINQ~

2019-11-14 16:11:11
字體:
來源:轉載
供稿:網友

本文內容

  • 引入
  • 實現 LINQ 的兩個前提
    • 擴展方法
    • λ 表達式
  • LINQ
  • 參考資料

本文說明 LINQ 是如何實現的,知道這點,才能更好地使用它~

如果你剛接觸 LINQ,那么可能不會那么快就理解。因為,LINQ 涉及的技術比較多,可以說它是眾多技術的集大成者,因此使用 LINQ 需要你對幾個知識點有一定認識,包括泛型委托、擴展方法、匿名函數、λ 表達式(Lambda 表達式),在此基礎上,才可能靈活運用 LINQ。這也是為什么 LINQ 在 VS 2008 才出現,而不是之前。

最好是,先學習泛型委托,再通過學習 System.Array 類提高對匿名函數和 λ 表達式的理解。

下載 Demo

引入


如果有一個關于一級方程式賽車冠軍 Racer 的集合 ,Racer 包括賽車手的姓名、國家、冠軍次數等屬性,要想對這個集合操作,比如檢索、排序等等,在 C# 3.0 以前,我們要想知道 Brazil 這個國家的冠軍都有誰,并且按降序排序,代碼如下所示:

IEnumerable<Racer> brazilChampions = champions.Where(
   delegate(Racer r)
   {
       return r.Country == "Brazil";
   }).OrderByDescending(
   delegate(Racer r)
   {
       return r.Wins;
   }).Select(
   delegate(Racer r)
   {
       return r;
   });

其中,champions 是冠軍集合。

注意:whereOrderByDescendingSelect 函數都把委托作為函數參數,鏈式調用最后會返回一個可用 foreach 語句迭代的 IEnumerable 可枚舉對象 brazilChampions

雖然上面代碼看上去還可以,但是,有 delegate 關鍵字、有形式參數,還不夠簡潔。是否可以沒有這些啰嗦的東西呢?估計你也想到了——λ 表達式!代碼如下所示:

IEnumerable<Racer> brazilChampions = champions.
   Where(r => r.Country == "Brazil").
   OrderByDescending(r => r.Wins).
   Select(r => r);

嗯,簡潔多了~可我們又想了,既然是查詢,那能不能像數據庫查詢那樣寫個 SQL 語句呢?比如:select * from champions t where t.country="Brazil" orderby desc 或類似形式,SQL 中有謂詞~

當然有,這就是 LINQ~

但 LINQ 不是一下冒出來的,它有個過程,這也是為什么 LINQ 在 VS 2008 才出現,而不是之前。

了解如何實現 LINQ,才能更好地使用它~

 

實現 LINQ 的兩個前提


要想了解 LINQ 是如何實現的,需要知道兩個必要的技術點:擴展方法和 λ 表達式。當然,還涉及到泛型委托。

擴展方法

其實,擴展方法并不陌生,我第一次注意這個用法是在 Ext.Net,它的項目里有個工具類程序集。其中的字符串工具類 StringUtils ,如判斷字符串是否為“空”,無論是 null,還是長度為 0 都返回 true,從而擴展 .Net 的字符串操作。如下所示 StringUtils 工具類的代碼片段:

public static class StringUtils
{
    /// <summary>
    /// Determine is the string is null or empty.
    /// </summary>
    /// <param name="text"></param>
    /// <returns></returns>
    public static bool IsEmpty(this string text)
    {
        return string.IsNullOrEmpty(text);
    }
    
    /// <summary>
    /// Determine is the string is NOT null or empty.
    /// </summary>
    /// <param name="text"></param>
    /// <returns></returns>
    public static bool IsNotEmpty(this string text)
    {
        return !text.IsEmpty();
    } 
 
    ……
 
    /// <summary>
    /// 
    /// </summary>
    /// <param name="text"></param>
    /// <param name="pattern"></param>
    /// <returns></returns>
    public static bool Test(this string text, string pattern)
    {
        return Regex.IsMatch(text, pattern);
    }
    
    /// <summary>
    /// 
    /// </summary>
    /// <param name="text"></param>
    /// <param name="pattern"></param>
    /// <param name="options"></param>
    /// <returns></returns>
    public static bool Test(this string text, string pattern, RegexOptions options)
    {
        return Regex.IsMatch(text, pattern, options);
    }
 
    ……
    
 }

顯然,.Net 沒有對字符串提供 IsEmpty Test 方法(其實,.Net 提供了 string.IsNullOrEmpty 方法),但如果在你的程序集中定義了這個類,那么就能在你的代碼中對字符串用“.”直接調用這些方法,如 "helloworld".IsEmpty()

注意,StringUtils 是靜態類。靜態類主要是為了共享,靜態類的成員也必須是靜態的。靜態類一般在程序加載的時候被構造。靜態類可以有構造函數,但只被調用一次。這樣,在你的代碼中就不需要實例化這個類,更重要的是,對函數參數 string 類型使用了 this 關鍵字。

因為,所有的泛型集合都繼承了 IEnumerable<T> 接口這樣,我們自定義過濾函數 Where,對 IEnumerable<T> 用擴展方法。如下所示,泛型集合根據指定條件返回符合條件的集合:

public static IEnumerable<T> Where(this IEnumerable<T> source, Func<T, bool> PRedicate)
{
    foreach (T item in source)
    {
        if (predicate(item))
            yield return item;
    }
}

其中,函數 Where 有兩個參數:一個是帶 thisIEnumerable<T>,另一個是 .net 提供的只有兩個輸入參數的帶返回值的泛型委托 Func<T, TResult>。這樣,對任何泛型集合調用 Where 方法都相當于:

champions.Where(Func<T, bool> predicate)

如:

IEnumerable<Racer> brazilChampions = champions.Where(
   delegate(Racer r)
   {
       return r.Country == "Brazil";
   });

既然自定義的泛型集合 Where 方法返回了 IEnumerable<T> 類型,我們當然可以再定義一個對泛型集合的排序函數,比如叫 OrderByDescending(this IEnumerable<T> source, Func<T, int> predicate)

因為自定義函數 Where 的返回類型,也是函數 OrderByDescending 的輸入類型,所以它們能形成一個調用鏈。

λ 表達式

C# 3.0 引入了一個新的語法——λ 表達式(Lambda 表達式)。λ 演算背后是有數學基礎的,也就是說,函數聲明,包括函數名、形參、返回類型等等都是可以沒有的,直接函數體。在對泛型集合調用上面自定義的 Where 函數時,就可以這樣寫:

IEnumerable<Racer> brazilChampions = champions.Where(r => r.Country == "Brazil");

其中,r 并沒有定義。這下代碼,簡潔多了。

前面說了擴展方法和 λ 表達式,現在離 LINQ 近了。

 

LINQ


我們希望 LINQ 跟 SQL 一樣,也有類 select、where、group by、order by 這些關鍵字,編譯器只要把這些關鍵字映射到相應的擴展方法上就行了。

而 LINQ 的關鍵字跟 SQL 很像,比如 from、where、orderby、descending 和 select 等。

上面的泛型查詢,改成 LINQ 如下所示:

var query = from r in champions
            where r.Country == "Brazil"
            orderby r.Wins descending
            select r;

其中,

  • 1,
where r.Country == "Brazil" 

轉換成

Where(r=>r.country=="Brazil");
  • 2,
orderby r.Wins descending

轉換成

OrderByDescending(r=>r.Wins)
  • 3,
select r

轉換成

Select()

LINQ 查詢必須以 from 子句開始,以 selectgroup 子句結束。在這兩個子句之間,可以使用 whereorderbyjion 和其他 from 子句。

LINQ 的具體用法你就得自己研究了,不在本文討論范圍內~

 

參考資料


  • .NET C# 聲明、實例化和使用委托以及委托在 C# 中的發展
  • 沒有 Lambda 演算何來匿名函數——匿名函數(匿名方法和 Lambda)、委托、LINQ
  • wiki λ演算
  • Database SQL Language Reference
  • .NET Framework System.Array.Sort 演示

 

下載 Demo


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 抚州市| 平南县| 威远县| 阿巴嘎旗| 乌审旗| 平凉市| 泰和县| 西吉县| 育儿| 汪清县| 新安县| 中西区| 自贡市| 德格县| 苍南县| 镶黄旗| 临洮县| 南京市| 淳化县| 无棣县| 开原市| 佛教| 南雄市| 金坛市| 岳阳县| 望奎县| 墨竹工卡县| 仪陇县| 靖西县| 萨嘎县| 罗平县| 康保县| 太原市| 宝坻区| 巩留县| 汕尾市| 张掖市| 黑龙江省| 河南省| 确山县| 东方市|