<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      LINQ之路 4:LINQ方法語(yǔ)法

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

      LINQ方法語(yǔ)法是非常靈活和重要的,我們?cè)谶@里將描述使用鏈接查詢運(yùn)算符的方式來(lái)創(chuàng)建復(fù)雜的查詢,方法語(yǔ)法的本質(zhì)是通過(guò)擴(kuò)展方法和Lambda表達(dá)式來(lái)創(chuàng)建查詢。C# 3.0對(duì)于LINQ表達(dá)式還引入了聲明式的查詢語(yǔ)法,通過(guò)查詢語(yǔ)法寫出的查詢比較類似于SQL查詢。本篇會(huì)對(duì)LINQ方法語(yǔ)法進(jìn)行詳細(xì)的介紹。

      當(dāng)然,.NET公共語(yǔ)言運(yùn)行庫(kù)(CLR)并不具有查詢語(yǔ)法的概念。所以,編譯器會(huì)在程序編譯時(shí)把查詢表達(dá)式轉(zhuǎn)換為方法語(yǔ)法,即對(duì)擴(kuò)展方法的調(diào)用。所以使用方法語(yǔ)法會(huì)讓我們更加接近和了解LINQ的實(shí)現(xiàn)和本質(zhì),并且一些查詢只能表示為方法調(diào)用,如檢索序列中的最大值、最小值元素的查詢,他們?cè)诓樵冋Z(yǔ)法中就沒(méi)有對(duì)應(yīng)的實(shí)現(xiàn)。但另一方面,查詢語(yǔ)法通常會(huì)比較簡(jiǎn)單和易讀。不管怎樣,這兩種語(yǔ)法和互相補(bǔ)充和兼容的,我們可以在一個(gè)查詢中混合使用方法語(yǔ)法和查詢語(yǔ)法。

      鏈接查詢運(yùn)算符

      在LINQ介紹中,我們示范了使用單個(gè)查詢運(yùn)算符創(chuàng)建的查詢。如果需要?jiǎng)?chuàng)建更加復(fù)雜的查詢,我們可以在表達(dá)式之后添加其他查詢運(yùn)算符,產(chǎn)生一個(gè)查詢鏈。如下例:查詢出所有含有字母”a”的姓名,按長(zhǎng)度進(jìn)行排序,然后把結(jié)果全部轉(zhuǎn)換成大寫格式。

              static void Main(string[] args)
      {
      string[] names = { "Tom", "Dick", "Harry", "Mary", "Jay" };

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

      foreach (string name in query) Console.WriteLine(name);
      }

      // Result:
      JAY
      MARY
      HARRY

      就像在本例中所示,當(dāng)鏈接使用查詢運(yùn)算符時(shí),一個(gè)運(yùn)算符的輸出sequence會(huì)成為下一個(gè)運(yùn)算符的輸入sequence,其結(jié)果形成了一個(gè)sequence的傳輸鏈,如圖所示:

         

           圖:鏈接查詢運(yùn)算符

      Where, OrderyBy, Select這些標(biāo)準(zhǔn)查詢運(yùn)算符對(duì)應(yīng)Enumerable類中的相應(yīng)擴(kuò)展方法。Where產(chǎn)生一個(gè)經(jīng)過(guò)過(guò)濾的sequence;OrderBy生成輸入sequence的排序版本;Select得到的序列中的每個(gè)元素都經(jīng)過(guò)了給定lambda表達(dá)式的轉(zhuǎn)換。

      下面是Where, OrderBy, Select這幾個(gè)擴(kuò)展方法的簽名:

              public static IEnumerable<TSource> Where<TSource>
      (this IEnumerable<TSource> source, Func<TSource, bool> predicate)

      public static IEnumerable<TSource> OrderBy<TSource, TKey>
      (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)

      public static IEnumerable<TResult> Select<TSource, TResult>
      (this IEnumerable<TSource> source, Func<TSource, TResult> selector)

       

      擴(kuò)展方法的重要性

      在LINQ表達(dá)式中,正是擴(kuò)展方法讓LINQ查詢運(yùn)算符的鏈接成為了可能。因?yàn)檫\(yùn)算符本身是對(duì)IEnumerable<T>類型的擴(kuò)展,并且返回IEnumerable<T>類型的結(jié)果。我們可以比較一下使用擴(kuò)展方法和使用靜態(tài)方法的區(qū)別,結(jié)果會(huì)一目了然。擴(kuò)展方法非常自然地反映了從左到右的數(shù)據(jù)流向,同時(shí)保持lambda表達(dá)式與查詢運(yùn)算符的位置一致性。

                  //   extension methods make LINQ elegant
      IEnumerable<string> query = names
      .Where(n => n.Contains("a"))
      .OrderBy(n => n.Length)
      .Select(n => n.ToUpper());

      // static methods lose query's fluency
      IEnumerable<string> query2 =
      Enumerable.Select(
      Enumerable.OrderBy(
      Enumerable.Where(names, n => n.Contains("a")
      ), n => n.Length
      ), n => n.ToUpper()
      );

       

      創(chuàng)建Lambda表達(dá)式

      在上例中,我們向Where運(yùn)算符提供了如下Lambda表達(dá)式:n => n.Contains(“a”)。對(duì)各個(gè)查詢運(yùn)算符來(lái)說(shuō),Lambda表達(dá)式的目的不盡相同。對(duì)于Where,它決定了一個(gè)element是否包含在結(jié)果sequence中;對(duì)于OrderBy,它把每個(gè)element映射到比較的鍵值;而對(duì)于Select,lambda表達(dá)式則決定了輸入sequence中的元素要怎么樣的轉(zhuǎn)換再放入輸出sequence中。

      關(guān)于Lambda表達(dá)式的詳細(xì)介紹,請(qǐng)參考LINQ 之路3:C# 3.0的語(yǔ)言功能(下)。

      通常來(lái)說(shuō),查詢運(yùn)算符會(huì)對(duì)每一個(gè)輸入sequence中的element來(lái)調(diào)用我們提供的Lambda表達(dá)式,這樣就給了我們一個(gè)實(shí)現(xiàn)自己的邏輯,從而得到自己需要結(jié)果的機(jī)會(huì)。我們可以看一下.NET Framework對(duì)Enumerable.Where的實(shí)現(xiàn):

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

      標(biāo)準(zhǔn)查詢運(yùn)算符使用了通用的Func委托,F(xiàn)unc是一組定義在System.Linq(謝謝 A_明~堅(jiān)持的指正,此處應(yīng)為System)命名空間中的通用委托。它接受一系列的輸入?yún)?shù)和一個(gè)返回值,返回值對(duì)應(yīng)最后一個(gè)參數(shù)定義。所以,F(xiàn)unc<TSource, bool>委托匹配 TSource => bool表達(dá)式,接受TSource輸入?yún)?shù),返回一個(gè)bool值。

      Lambda表達(dá)式和元素類型

      標(biāo)準(zhǔn)查詢運(yùn)算符使用統(tǒng)一的類型名稱:

      通用類型名稱

      用途

      TSource

      Input sequence中的element類型

      TResult

      Output sequence中的element 類型(如果和TSource不相同)

      TKey

      使用sorting、grouping、joining等的鍵值類型

      TSource由輸入sequence決定,而TResult和TKey則從我們提供的Lambda表達(dá)式推斷得到。

      比如:Select查詢運(yùn)算符的簽名如下:

              public static IEnumerable<TResult> Select<TSource,TResult>(
      this IEnumerable<TSource> source, Func<TSource,TResult> selector)

      Func<TSource,TResult>匹配TSource => TResult的Lambda表達(dá)式,接受一個(gè)輸入?yún)?shù)TSource,返回TResult。因?yàn)門Source和TResult是不同的類型,所以我們的Lambda表達(dá)式甚至可以改變輸入element的數(shù)據(jù)類型。下面的示例就把string類型元素轉(zhuǎn)換為int類型元素:

              static void TestSelectOperator(){
      string[] names = { "Tom", "Dick", "Harry", "Mary", "Jay" };
      // 編譯器將會(huì)從Lambda表達(dá)式 n => n.Length推斷出TResult為int類型
      IEnumerable<int> query = names.Select(n => n.Length);

      foreach (int length in query)
      Console.Write(length + "|"); // 3|4|5|4|3
      }

      而對(duì)Where查詢運(yùn)算符來(lái)講,它并不需要對(duì)輸出element進(jìn)行類型推斷,因?yàn)樗皇菍?duì)輸入elements進(jìn)行過(guò)濾而不作轉(zhuǎn)換,因此輸出element和輸入element具有相同的數(shù)據(jù)類型。

      對(duì)于OrderBy查詢運(yùn)算符來(lái)講,F(xiàn)unc<TSource, TKey>把輸入元素映射至一個(gè)排序鍵值。TKey由Lambda表達(dá)式的結(jié)果推斷出來(lái),比如我們可以按長(zhǎng)度或按字母順序?qū)ames數(shù)組進(jìn)行排序:

                  string[] names = { "Tom", "Dick", "Harry", "Mary", "Jay" };
      IEnumerable<string> sortedByLength, sortedAlphabetically;
      sortedByLength = names.OrderBy(n => n.Length); // int key
      sortedAlphabetically = names.OrderBy(n => n); // string key

       

      其他查詢運(yùn)算符

      并不是所有的查詢運(yùn)算符都返回一個(gè)sequence。元素(element)運(yùn)算符會(huì)從輸入sequence中獲取單個(gè)元素,如:First,Last和ElementAt:

                  int[] numbers = { 10, 9, 8, 7, 6 };  
      int firstNumber = numbers.First(); // 10
      int lastNumber = numbers.Last(); // 6
      int secondNumber = numbers.ElementAt(1); // 9
      int lowestNumber = numbers.OrderBy(n => n).First(); // 6

      集合(aggregation) 運(yùn)算符返回一個(gè)標(biāo)量值,通常是數(shù)值類型:

                  int count = numbers.Count();    // 5
      int min = numbers.Min(); // 6

      判斷運(yùn)算符返回一個(gè)bool值:

                  bool hasTheNumberNine = numbers.Contains(9);    // true
      bool hasElements = numbers.Any(); // true
      bool hasAnOddElement = numbers.Any(n => (n % 2) == 1); //true

      因?yàn)檫@些運(yùn)算符并不是返回一個(gè)sequence,所以我們不能再這些運(yùn)算符之后鏈接其他運(yùn)算符,換句話講,他們一般出現(xiàn)在查詢的最后面。

      還有一些查詢運(yùn)算符接受兩個(gè)輸入sequence,比如Concat把一個(gè)sequence添加到另外一個(gè)sequence后面;Union與Concat類似,但是會(huì)去除相同的元素:

                  int[] seq1 = { 1, 2, 2, 3 };
      int[] seq2 = { 3, 4, 5 };
      IEnumerable<int> concat = seq1.Concat(seq2); // { 1, 2, 2, 3, 3, 4, 5 }
      IEnumerable<int> union = seq1.Union(seq2); // { 1, 2, 3, 4, 5 }

      本篇只是對(duì)幾個(gè)常用的查詢運(yùn)算符做了介紹,在后續(xù)篇章中,我會(huì)對(duì)更多地運(yùn)算符進(jìn)行更詳細(xì)的討論。

      posted @ 2011-10-27 14:48  Life a Poem  閱讀(23621)  評(píng)論(32)    收藏  舉報(bào)
      主站蜘蛛池模板: XXXXXHD亚洲日本HD| 丁香婷婷在线观看| 成人国产乱对白在线观看| 2019亚洲午夜无码天堂| 中文字幕亚洲中文字幕无码码| 这里只有精品免费视频| 日韩卡一卡2卡3卡4卡| 偷偷做久久久久免费网站| 十八禁午夜福利免费网站| 麻豆蜜桃伦理一区二区三区| 国产精品久久中文字幕| 午夜dv内射一区二区| 国产suv精品一区二区五| 亚洲中文字幕一二三四区| 国产一区精品综亚洲av| 国产欧美综合在线观看第十页| 爱色精品视频一区二区| 无线乱码一二三区免费看| 亚洲一区二区偷拍精品| 经典国产乱子伦精品视频| 亚洲熟妇色自偷自拍另类| 九九热视频在线观看视频| 亚洲春色在线视频| 人妻无码∧V一区二区| 亚洲一区二区三区色视频| 欧美老少配性行为| 国产精品视频免费一区二区三区| 亚洲欧洲一区二区综合精品| 色老头亚洲成人免费影院 | 国产毛片基地| 日韩精品不卡一区二区三区| 亚洲AV日韩AV综合在线观看| 国产色a在线观看| 在线精品另类自拍视频| a男人的天堂久久a毛片| 亚洲av日韩av中文高清性色| 中文字幕自拍偷拍福利视频| 国产精品人妻在线观看| 久久AV中文综合一区二区| 日韩亚av无码一区二区三区| 国产真实伦在线观看视频|