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岁以下的拥有奔驰的干爹