LINQ标准的查询操作符

时间:2021-07-06 01:55:37

LINQ标准的查询操作符

首先我们来看一下LINQ的操作符,可根据查询操作符的操作”类型”进行分类,如把它们分成投影,限制,排序,联接,分组,串联,聚合,集合,生成,转换,元素,相等,量词,分割等.

类型

 

操作符名称

 

投影操作符

 

Select,SelectMany

 

限制操作符

 

Where

 

排序操作符

 

OrderBy,OrderByDescending,ThenBy,ThenByDescending,Reverse

 

联接操作符

 

Join,GroupJoin

 

分组操作符

 

GroupBy 

 

串联操作符

 

concat

 

聚合操作符

 

Aggregate,Average,Count,LongCount,Max,Min,Sum

 

集合操作符

 

Distinct,Union,Intersect,Except

 

生成操作符

 

Empty,Range,Repeat

 

转换操作符

 

AsEnumerable,Cast,OfType,ToArray,ToDictionary,ToList,ToLookup

 

元素操作符

 

DefaultIfEmpty,ElementAt,ElementAtOrDefault,First,Last,FirstOrDefault, LastOrDefault,Single,SingleOrDefault

 

相等操作符

 

SequenceEqual

 

量词操作符

 

All,Any,Contains

 

分割操作符

 

Skip,SkipWhile,Take,TakeWhile

 

演示案例:

using System;

using System.Collections;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

namespace LINQ查询操作符

{

class Program

{

static void Main(string[] args)

{

//将这些Person类的实例化对象存放到list1中

IEnumerable<Person> list1 = GetMyList();

//使用LINQ的过滤操作符

var query1 = from p in list1 where p.age >= 20 select p;

Console.WriteLine("将年龄大于20的人输出出来 : ");

PrintMyInfo(query1);

//下面我们写一个对象查询的版本

Console.WriteLine("对象版本的过滤 : ");

list1 = list1.Where<Person>(per => { return per.age >= 30; }).Select(per => per);

PrintMyInfo(list1);

/*索引过滤

* 这是一个无法使用LINQ语句来实现的功能,它是where方法的重载

* 在这个方法中,可以穿入第二个参数----索引

* 可以是过滤器返回个数的计数器,可以在表达式中使用这个索引,执行基于索引的计算

* public delegate TResult Func<T1,T2,TResult>(T1 arg1mT2 arg2);委托重载

*/

IEnumerable<Person> list2 = GetMyList();

list2 = list2.Where<Person>((p1, p2) => p1.name.StartsWith("a") && p2 <= 1);//从0开始计数

Console.WriteLine("只输出姓名以a字母开头的,并且只要两个人,多了不要");

PrintMyInfo(list2);

/*

* 类型过滤

* 假定一个数组包含有整型,与字符型元素,而我们只想过滤出字符型元素.             

*/

object[] objs = new object[] { 232, 23, 3232, "syx", 343, 23456, "zsf" };

//就是这么牛,不用解释

var query2 = objs.OfType<string>();

Console.WriteLine("类型过滤,只要string类型的 :");

foreach (var item in query2)

{

Console.WriteLine(item);

}

/*复合的form子句

* 如果需要根据对象的一个成员过滤,而该成员本身又是一个个系列,就要用到复合子句.

* 案例:我们想找一个年龄在25以上,并且有奔驰的人(一个人可以有多个车),认他当干爹

*/

IEnumerable<Person> list3 = GetMyList();

Console.WriteLine("认干爹的任务 : ");

var query3 = from p in list3 from c in p.list where c.name.Equals("奔驰") where p.age >= 25 select p;

PrintMyInfo(query3);

/*

* 下面来分析一下select投影方法

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

* Select<TSource,TResult>方法定义了两个泛型类型,源,返回类型

* IEnumerable<TResult>返回可以迭代的类型

* 两个参数: this IEnumerable<TSource> source 是指本方法要扩展IEnumerable<TSource>类型

* Func<TSource, TResult> selector委托

* 委托的声明: public delegate TResult Func<T, TResult>(T arg)

*/

IEnumerable<Person> list4 = GetMyList();

var query4 = list4.Select(p => p.age);

/*

* select第一个参数是隐式的,所以我们不用关心,只要明白它是扩展就可以了,

* 第二个参数通过源类型,返回一个投影类型,可以是源类型的一个字段,也可以将

* 源类型直接返回,也就是我们直接写select p

* 以上实例,我们是将源类型中的age返回,它是int类型.下面我们迭代,就不可以用Person来迭代了

*/

Console.WriteLine("年龄投影");

foreach (var item in query4)

{

Console.WriteLine(item);

}

/*

* 在select和where这两个方法上,可能会存在一点误解,我开始认为select和where可以做相同的问题

* 比如,都是可以进行筛选             

*/

var query5 = list4.Select(p =>

{

if (p.age >= 25)

{

return new Person(p.name, p.age);

}

else

{

return new Person("node", 1);

}

});

/*

* 上述代码是用来过滤年龄超过25岁的人,但是无法将不需要的部分清楚,所以

* 还是没办法与where一样的功能.

* where方法,返回的是bool,可以筛选不合格条件的

*/

Console.WriteLine("select模拟where");

foreach (var item in query5)

{

Console.WriteLine(item.name);

}

//看完了select我们接着看SelectMany方法,其实复合查询中,就是用到了这个方法。

//public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(

//    this IEnumerable<TSource> source,

//    Func<TSource, IEnumerable<TCollection>> collectionSelector,

//    Func<TSource, TCollection, TResult> resultSelector

//)

//返回IEnumerable<TResult>

//3个参数,,第一个是隐式的,也就是指明他扩展的是哪种类型的this IEnumerable<TSource> source

//第二个参数,是一个委托 Func<TSource, IEnumerable<TCollection>> collectionSelector,

//下面我们看这个委托的声明:public delegate TResult Func<T, TResult>( T arg )

//这里与select方法有一点不同,select用委托做参数时保留了TResult类型,而这里我们指定成了IEnumerable<TCollection>>

//第三个参数,同样也是一个委托 Func<TSource, TCollection, TResult> resultSelector

//public delegate TResult Func<T1, T2, TResult>(T1 arg1,T2 arg2)

IEnumerable<Person> list5 = GetMyList();

//以下实例是SelevtMany方法的一个重载,只是将一个序列的子集序列查出来

var query6 = list5.SelectMany(per => per.list).Where(p => p.name.Equals("奔驰"));

Console.WriteLine("查询序列的序列 :");

foreach (var item in query6)

{

Console.WriteLine(item.name);

}

//用对象方法的方式来查询一次所有25岁以下的拥有奔驰的干爹