LINQ學習(擴展方法,委托,Lambda表達式) 第二篇


  1. LINQ基本查詢操作符-獲取數據

(1) select()  語法是:

public static IEnumerable<TResult> select<TSource,TResult>(

   this IEnumerbale<TSource> source.

Func<TSource,TResult> selector)

說明:1) select方法本身是一個泛型擴展方法

 2) 它作用於IEnumerable<TSource>類型

 3) 他只接受一個Func<TSource,TResult>類型參數

 4) Func<TSource,TResult>是一個泛型委托,位於System名字的空間下,System.Core.dll中,在這里Selector是一個提取器。

 (2) 舉例說明,先定義一個靜態類ExtraClass,然后再靜態類中在定義一個靜態的擴展方法,實現輸出信息。代碼如下:

public static class ExtraClass

    {

        //為IEnumerable提供輸出的方法

        public static void Print(this IEnumerable<string> ie)

        {

            IEnumerator<string> result = ie.GetEnumerator();

            while (result.MoveNext())

            {

                MessageBox.Show(result.Current);

            }

        }

}

然后如圖所示,單擊圖上的按鈕事件,在按鈕事件中的代碼是:

 

此事件下面的代碼實現了將一個泛型集合中的數據循環顯示出來,代碼如下:

List<string> persons = new List<string>();

    persons.Add("zhang san");

    persons.Add("zhang san feng");

    persons.Add("li si");

    persons.Add("wang wu");

    persons.Add("wang liu");

    persons.Add("li ba");

    persons.Add("lao wu");

    persons.Add("zhang xx");

    //輸出persons里面的所有的元素

    var result = persons.Select(p => p);

result.Print();

執行結果是按順序循環輸出。

2. LINQ基本查詢操作符-過濾數據

(1) where() 語法是:

  public static IEnumerable<TSource> where<TSource>(

      this IEnumerable<TSource> source,

Func<TSource,bool> predicate)

說明:1) where方法是一個泛型擴展方法

 2) 它和select()一樣作用與IEnumerable<TSource>類型

 3) 它只接受一個Func<TSource,bool>泛型委托參數,在這里predicate是一個判斷條件。

(2) 舉例說明,還是上面的例子,使用那個泛型集合,實現按照一定的條件輸出信息。先創建一個方法,實現輸出姓“zhang”的人的信息,代碼如下:

public bool Judge(string s)

        {

            if (s.StartsWith("zhang"))

            {

                return true;

            }

            return false;

        }

  在select控件的事件下面用LINQ代碼輸出只是姓張的各種各樣的實現代碼:

//輸出persons里面姓“zhang”的人

     //var result = persons.Where(p => p.StartsWith("zhang"));  //第一種方法

     //var result = persons.Select(p => p).Where(p => p.StartsWith("zhang")); //第二種方法

     //var result = persons.Where(p => p.StartsWith("zhang")).Select(p => p);  //第三種方法

     var result = persons.Where(p => Judge(p));   //第四種方法

     result.Print();

3. LINQ基本查詢操作符-排序數據

(1) OrderBy()  語法是:

  pblic static IOrderedEnumerable<TSource> orderBy<TSource,TKey>(

        this IEnumerable<TSource> source

       Func<TSource,TKey> keySelector)

注:1) orderBy方法也是一個泛型擴展方法

 2) 它和select()一樣作用與IEnumerable<TSource>類型

 3) 它只接收一個Func<TSource,Tkey>類型參數,在這里keySelctor指定要排序的字段。

 4) 如果想要降序排列可以使用orderbyDescending方法。

(2) 舉例說明,同上例,實現排序的代碼如下:

//var result = persons.OrderBy(p => p);

       //按照名字的最后一個字母排序

       //var result = persons.OrderBy(p => p.Substring(p.Length - 1, 1)).Select(p => p);

       //降序排列

       var result = persons.OrderByDescending(p => p);

       result.Print();

  1. Linq基本查詢操作符-分組數據

(1) GroupBy()  語法是:

   public static IEnumerable<IGrouping<Tkey,TSource>>

               GroupBy<TSource,TKey>(

                      this IEnumerable<TSource> source,

                      Func<TSource,TKey> keySelector  )

說明:1) GroupBy()方式和OrderBy()方式非常類似,它也是一個泛型擴展方法。

2) 它和OrderBy()一樣作用與IEnumerable<TSource>類型。

3) 它只接受一個Func<TSource,TKey>類型參數,在這里keySelector指定要分組的字段。

(2) 舉例說明,同上例,實現分組的代碼是:

//分組---按照姓名來分組¦--取出姓名中的空格前的部分

     var result = persons.GroupBy(p => p.Split(new char[] { ' ' })[0]);

    foreach (var group in result)

    {

         Console.WriteLine("姓:" + group.Key);

         foreach (var name in group)

          {

               Console.WriteLine("\t" + name);

          }

          Console.WriteLine();

     }

  1. 查詢執行的時機

(1) 從前面的試驗中,我們發現一次查詢實際上經過以下3步。

 1) 第一步:獲取數據源  int[] numbers=new int[]{3,45,65,76,2,434,54,65,76,76,65,43};

  2) 第二步:定義查詢  var even=numbers.Where(p=>p%2==0).Select(p=>{

Console.WriteLine(“Hi!”+p.ToString());

return p;     });

  3) 第三步:執行查詢   foreach(var item in even){   }

  1. 查詢執行的時機小節

(1) 查詢分為以下三步,獲取數據源,定義查詢,執行查詢

(2) 定義查詢后,查詢直到需要枚舉結果時才被真正執行,這種方法稱為”延遲執行”。

(3) 當查詢結果返回單一值時,查詢立即執行。舉例,如代碼:

         //查詢時機---當返回值為單值時馬上執行語句,負責延遲執行

      var result = persons.Select(p => p).Count();

      Console.WriteLine("個數是" + result);

(4) 因此,可以通過以下技巧在定義查詢時就強制執行查詢

  1. Linq查詢的兩種方式

(1) Method syntax,查詢方法方式

  主要利用System.Linq.Enumerable類中定義的擴展方法和Lambda表達式方式進行查詢。

(2) Query syntax ,查詢語句方式

  1. 查詢語句VS查詢方法

注:查詢語句和查詢方法存在着緊密的關系

(1) CLR本身並不理解查詢語句,它只理解查詢方法。

(2) 編譯器負責在編譯時將查詢語句翻譯為查詢方法。

(3) 大部分查詢方法都有對應的查詢語句形式,如:Select()對應select,OrderBy()對應orderby。

(4)部分查詢方法目前在C#中還沒有對應的查詢語句:如:Count()和Max()這時只能采用以下替代方案

  1) 查詢方法

  2) 查詢語句+查詢方法的混合方式

(5) 一般情況下,建議使用可讀性更好的查詢語句。舉例說明:

還是用上面多定義的泛型集合數組persons,用查詢語句實現幾個簡單的功能,代碼如下:

//輸出persons中的所有的元素

var result = from p in persons select p;

    //輸出persons中姓zhang的人----語句和方法的混合編排?

     var result = (from p in persons select p).Where(p => p.StartsWith("zhang"));

     //排序

      var result = from p in persons orderby p select p;

      result.Print();

  1. 高級查詢方法

(1) 聚合類  Count(),Max()/Min(),Average(),Sum()。舉例說明:

 重新定義一個數組來實現上面的各種各樣的方法,代碼如下:

   //LINQ to Objects查詢高級方法

      //數組數據arr

      int[] arr = { 23, 34, 5, 5, 23, 45, 65, 33, 43, 76, 67, 87 };

      //聚合類

      Console.WriteLine("arr的最大值: + arr.Max());

      Console.WriteLine("arr的最小值¦: " + arr.Min());

      Console.WriteLine("arr的平均值¦: " + arr.Average());

      Console.WriteLine("arr的數組元素個是" + arr.Count());

      Console.WriteLine("arr的總和是: " + arr.Sum());

(2) 排序類  thenBy()  代碼如下:

      //排序類

      var result = arr.OrderBy(p => p.ToString().Substring(0, 1));

      //2次排序混編模式沒有達到要求

      var result = arr.OrderBy(p => p.ToString().Substring(0, 1)).ThenBy(p => p);

      //按照語句排序

      var t = arr.OrderBy(p => p.ToString().Substring(0, 1));

      var result = from p in t orderby p descending select p;

(3) 分區類  Take,TakeWhile,Skip,SkipWhile   代碼如下:

      //分區類

      var result = arr.Skip(3).Take(3);  //跳過三個值取三個值

      var result = arr.Skip(3);  //跳過幾個值

var result = arr.SkipWhile(p => p > 4); //方法體部分是該Linq語句不在往后執行的條件,當第一次遇到條件成立時,取剩下的所有元素

      var result = arr.TakeWhile(p => p > 4); //方法體部分是該Linq語句提取數據的條件,當第一次遇到條件不成立的情況就停止執行

(4) 集合類   Distinct   代碼如下:

      //集合類

      var result = arr.Distinct();

(5) 生成類   Range,Repeat   代碼如下:

      //生成類-----靜態類

       var result = System.Linq.Enumerable.Range(10, 50);

       var result = System.Linq.Enumerable.Range('a', 50); //生成連續的序列

       var result = System.Linq.Enumerable.Repeat(40, 10);

       result.Print();

  1. 生成類查詢方法小結

注:使用生成類查詢方法時,需要注意以下幾點:

(1) 和其它幾類方法不同,Range/Repeat不是擴展方法,而是普通的靜態方法

(2) Range只能產生整數序列。

(3) Repeat可以產生泛型序列。

(4) 所有的查詢方法都存放在System.Linq.Enumerable靜態類中。


免責聲明!

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



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