转载LINQ学习扩展方法,委托,Lambda表达式 第二篇

转载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静态类中。

赞(0) 打赏
分享到: 更多 (0)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏