本节我们来学习一下linq的标准查询操作符部分: 

LINQ中涉及到的延时标准查询操作符很多,这里将其分为两节内容来讲解。对于每个具体的标准查询操作符将从:操作符的作用、方法原型、原型说明以及示例验证三方面来讲解。

  1.Where操作符

  (1)作用:用于限定输入集合中的元素,将符合条件的元素组织生成一个序列;

  (2)方法原型

    ①原型定义:

    publlic static IEnumerable<T> Where<T>(

    this IEnumerable<T> source,

    Func<T,bool> predicate);    

    ②原型定义:

    publlic static IEnumerable<T> Where<T>(

    this IEnumerable<T> source,

    Func<T,int,bool> predicate); 

  (3)原型说明:尽管Where操作符有两种原型定义,但两种方法基本相似。都是接收一个输入序列参数source和一个委托类型参数predicate,返回一个序列对象集合。当在source输入序列上调用Where操作符时,系统将输入序列source中的每一个元素作为委托predicate的输入参数传递给对应于该委托的具体方法(一般为Lambda表达式或匿名方法),只有使得委托predicate的返回值为true的元素才会被添加到序列对象的结果中去。相比较于第一种方法原型,第二种方法的委托参数稍有不同,多了一个类型为int输入参数,其代表输入序列中元素的下标值(注:下标从0开始);

  (4)示例验证

Where操作符
 1         static void Main(string[] args)
2 {
3 //定义数据源
4 string[] array = new string[] {"Hello","Linq","To","Object","!" };
5
6 //Where第一个原型
7 Console.WriteLine("调用Where操作符第一个方法原型:");
8 Console.WriteLine("--------------------------------");
9
10 var items = array.Where(str => str.StartsWith("L"));
11
12 foreach (var str in items)
13 {
14 Console.WriteLine("L带头的字符串有:{0}",str);
15 }
16
17 Console.WriteLine("****************************************");
18
19 //Where第二个原型
20 Console.WriteLine("调用Where操作符第二个方法原型:");
21 Console.WriteLine("--------------------------------");
22
23 var items1 = array.Where((str,i) => str.StartsWith("L")||i>1);
24
25 foreach (var str in items1)
26 {
27 Console.WriteLine("L带头或元素下标值大于1的字符串:{0}", str);
28 }
29
30 Console.Read();
31 }

结果

  2.Select操作符

  (1)作用:用于根据输入序列中的元素创建相应的输出序列中的元素,输出序列的元素类型可以和输入序列中的元素类型相同;

  (2)方法原型

    ①原型定义:

    publlic static IEnumerable<S> Select<T,S>(

    this IEnumerable<T> source,

    Func<T,S> selector);    

    ②原型定义:

    publlic static IEnumerable<S> Select<T,S>(

    this IEnumerable<T> source,

    Func<T,int,S> selector); 

  (3)原型说明:两种方法原型都是接收一个输入序列参数source和一个委托类型参数selector,返回一个新的序列对象结果。其中S可以与T的类型相同,也可不同。Select操作符把输入序列source中的每一个元素作为委托selector的参数传递给对应于该委托的具体方法(一般为Lambda表达式或匿名方法),委托selector会根据传递进来类型为T的参数生成一个类型为S的对象并返回该对象。相比较于第一种方法原型,第二种方法的委托参数稍有不同,多了一个类型为int输入参数,其代表输入序列中元素的下标值; 

  (4)示例验证

Select操作符
 1         static void Main(string[] args)
2 {
3 //定义数据源
4 string[] array = new string[] {"Hello","Linq","To","Object","!" };
5
6 //Select第一个原型
7 Console.WriteLine("调用Select操作符第一个方法原型:");
8 Console.WriteLine("--------------------------------");
9
10 var items2 = array.Select(str => str.Length);
11
12 Console.WriteLine("数组中各个字符串的长度:");
13 foreach (var i in items2)
14 {
15 Console.WriteLine(i);
16 }
17
18 Console.WriteLine("****************************************");
19
20 //Select第二个原型
21 Console.WriteLine("调用Select操作符第二个方法原型:");
22 Console.WriteLine("--------------------------------");
23
24 var items3 = array.Select((str, i)=> new {index=i,Length=str.Length});
25
26 foreach (var i in items3)
27 {
28 Console.WriteLine("下标为{0}字符串长度为{1}", i.index,i.Length);
29 }
30
31 Console.Read();
32 }

结果

  3.SelectMany操作符

  (1)作用:用于根据输入序列中的么一个元素,在输出序列中创建相应的零个或多个元素;

  (2)方法原型

    ①原型定义:

    publlic static IEnumerable<S> SelectMany<T,S>(

    this IEnumerable<T> source,

    Func<T,IEnumerable<S>> selector);    

    ②原型定义:

    publlic static IEnumerable<S> SelectMany<T,S>(

    this IEnumerable<T> source,

    Func<T,int,IEnumerable<S>> selector); 

  (3)原型说明:两种方法原型都是将输入序列source中每个元素传递给委托selector,委托selector根据每一个传递进来类型为T的元素,返回一个由类型为S的元素组成的新序列。需要注意的是SelectMany操作符所返回的新序列,是由每次调用委托selector生成的新序列元素组合而成,与前两个操作符一样,SelectMany的第二种方法相比较于第一种方法原型,在委托参数上稍有不同,多了一个类型为int输入参数,其代表输入序列中元素的下标值;

  (4)示例验证

SelectMany操作符
 1         static void Main(string[] args)
2 {
3 //定义数据源
4 string[] array = new string[] {"Hello","Linq","To","Object","!" };
5
6 //SelectMany第一个原型
7 Console.WriteLine("调用SelectMany操作符第一个方法原型:");
8 Console.WriteLine("--------------------------------");
9
10 var items4 = array.SelectMany(str =>str.ToArray());
11
12 Console.WriteLine("数组中各个字符:");
13 foreach (var i in items4)
14 {
15 Console.Write(i);
16 }
17
18 Console.WriteLine("\n****************************************");
19
20 //SelectMany第二个原型
21 Console.WriteLine("调用SelectMany操作符第二个方法原型:");
22 Console.WriteLine("--------------------------------");
23
24 var items5 = array.SelectMany((str, i) =>i>0?str.ToArray():new char[]{});
25
26 Console.WriteLine("下标大于1所有字符串的字符:");
27 foreach (var i in items5)
28 {
29 Console.Write(i);
30 }
31
32 Console.Read();
33 }

结果

  4.Take操作符

  (1)作用:用于从输入序列中返回指定数量的元素;

  (2)方法原型

    publlic static IEnumerable<T> Take<T>(

    this IEnumerable<T> source,

    int count);    

  (3)原型说明:Take操作符从从输入序列中source中的第一个元素开始,顺序取count个元素组成一个新的序列作为返回结果。如果参数count的值大于输入序列元素的个数,那么将返回由输入序列中所有元素组成的新序列;

  (4)示例验证

Take操作符
 1         static void Main(string[] args)
2 {
3 //定义数据源
4 string[] array = new string[] {"Hello","Linq","To","Object","!" };
5
6 Console.WriteLine("调用Take操作符:");
7 Console.WriteLine("--------------------------------");
8
9 var items6 = array.Take(1);
10
11 foreach (var str in items6)
12 {
13 Console.WriteLine("从下标0开始向右取1个元素:{0}", str);
14 }
15
16 Console.Read();
17 }

结果

  5.TakeWhile操作符

  (1)作用:用于从输入序列中返回指定数量且满足一定条件的元素;

  (2)方法原型

    ①原型定义:

    publlic static IEnumerable<T> TakeWhile<T>(

    this IEnumerable<T> source,

    Func<T,bool> predicate);    

    ②原型定义:

    publlic static IEnumerable<T> TakeWhile<T>(

    this IEnumerable<T> source,

    Func<T,int,bool> predicate); 

  (3)原型说明:从两个原型定义式中可以看到它们和操作符Where的原型定义一模一样,但是两者的方法实现确是完全不同的。TakeWhile操作符调用时,会将source序列中的每一个元素按照顺序传递给委托predicate,只有那些使得委托predicate的返回值为true的元素才会被添加到结果序列中,但是一旦遇到一个元素使得委托predicate的返回值为false的话,输入序列中的剩余元素就不再处理。而Where则凡是使得委托predicate的返回值为true的元素都被添加到结果序列中;

  (4)示例验证

TakeWhile操作符
 1         static void Main(string[] args)
2 {
3 //定义数据源
4 string[] array = new string[] {"Hello","Linq","To","Object","!" };
5
6 //TakeWhile第一个原型
7 Console.WriteLine("调用TakeWhile操作符第一个方法原型:");
8 Console.WriteLine("--------------------------------");
9
10 var items7 = array.TakeWhile(str => str.StartsWith("L"));
11
12 foreach (var str in items7)
13 {
14 Console.WriteLine("L带头的字符串有:{0}", str);
15 }
16
17 Console.WriteLine("****************************************");
18
19 //TakeWhile第二个原型
20 Console.WriteLine("调用TakeWhile操作符第二个方法原型:");
21 Console.WriteLine("--------------------------------");
22
23 var items8 = array.TakeWhile((str, i) => str.StartsWith("L") || i > 1);
24
25 foreach (var str in items8)
26 {
27 Console.WriteLine("L带头或元素下标值大于1的字符串:{0}", str);
28 }
29
30 Console.Read();
31 }

结果发现尽管示例代码和Where操作符中的示例代码一样,但是TakeWhile操作符的运行情况确是没有任何输出结果):

  6.Skip操作符

  (1)作用:用于从输入序列中跳过指定个数的元素,返回由序列中剩余的元素所组成的新序列;

  (2)方法原型

    publlic static IEnumerable<T> Skip<T>(

    this IEnumerable<T> source,

    int count);

  (3)原型说明:与Take操作符方法原型相同,同样的如果参数count的值大于输入序列元素的个数,Skip操作符则返回一个空的序列;

  (4)示例验证

Skip操作符
 1         static void Main(string[] args)
2 {
3 //定义数据源
4 string[] array = new string[] {"Hello","Linq","To","Object","!" };
5
6 Console.WriteLine("调用Skip操作符:");
7 Console.WriteLine("--------------------------------");
8
9 var items9 = array.Skip(1);
10
11 Console.WriteLine("从下标0开始跳过1个元素,剩余字符串:");
12 foreach (var str in items9)
13 {
14 Console.WriteLine(str);
15 }
16
17 Console.Read();
18 }

结果

  7.SkipWhile操作符

  (1)作用:用于从输入序列中跳过满足一定条件指定数量的元素,返回由序列中剩余的元素所组成的新序列;

  (2)方法原型

    ①原型定义:

    publlic static IEnumerable<T> SkipWhile<T>(

    this IEnumerable<T> source,

    Func<T,bool> predicate);    

    ②原型定义:

    publlic static IEnumerable<T> SkipWhile<T>(

    this IEnumerable<T> source,

    Func<T,int,bool> predicate); 

  (3)原型说明:两个原型定义和TakeWhile操作符相同,当使用SkipWhile操作符时,会将输入序列source中的每一个元素顺序地传递给委托参数predicate,是要使委托predicate返回值为true,就跳过该元素,直到遇到一个使委托predicate返回值为false的元素为止,接下来把该元素和输入序列中剩余的元素组成新的序列返回,与TakeWhile一样,SkipWhile的第二种方法相比较于第一种方法原型,在委托参数上稍有不同,多了一个类型为int输入参数,其代表输入序列中元素的下标值;

  (4)示例验证

SkipWhile操作符
 1         static void Main(string[] args)
2 {
3 //定义数据源
4 string[] array = new string[] {"Hello","Linq","To","Object","!" };
5
6 //SkipWhile第一个原型
7 Console.WriteLine("调用SkipWhile操作符第一个方法原型:");
8 Console.WriteLine("--------------------------------");
9
10 var items10 = array.SkipWhile(str => str.StartsWith("H"));
11
12 Console.WriteLine("跳过H带头元素,剩余字符串:");
13 foreach (var str in items10)
14 {
15 Console.WriteLine(str);
16 }
17
18 Console.WriteLine("****************************************");
19
20 //SkipWhile第二个原型
21 Console.WriteLine("调用SkipWhile操作符第二个方法原型:");
22 Console.WriteLine("--------------------------------");
23
24 var items11 = array.SkipWhile((str, i) => str.StartsWith("T") || i <2);
25
26 Console.WriteLine("跳过L带头或元素下标值小于2的字符串,剩余字符串:");
27 foreach (var str in items11)
28 {
29 Console.WriteLine(str);
30 }
31
32 Console.Read();
33 }

结果

  8.Concat操作符

  (1)作用:用于连接两个序列,生成一个新的序列;

  (2)方法原型

    publlic static IEnumerable<T> Concat<T>(

    this IEnumerable<T> first,

    this IEnumerable<T> second);

  (3)原型说明:Concat操作符接受first和second两个输入序列,且两个输入序列的类型必须一样,根据这两个输入序列中的元素生成一个包含全部元素的新序列作为返回值;

  (4)示例验证

Concat操作符
 1         static void Main(string[] args)
2 {
3 //定义数据源
4 string[] array = new string[] {"Hello","Linq","To","Object","!" };
5 string[] array1 = new string[] {"Nice","To","Meet","You"};
6
7 Console.WriteLine("调用Concat操作符:");
8 Console.WriteLine("--------------------------------");
9
10 var items12 = array.Concat(array1);
11
12 Console.WriteLine("连接后的字符串:");
13 foreach (var str in items12)
14 {
15 Console.Write(str+" ");
16 }
17
18 Console.Read();
19 }

结果

  9.OrderBy操作符

  (1)作用:用于对输入序列中的元素基于一个委托方法的返回值进行顺序排序;

  (2)方法原型

    ①原型定义:

    public static IOrderedEnumerable<T> OrderBy<T,K>(

    this IEnumerable<T> source,

    Func<T,K> keySelector)

    where K:IComparable<K>;

    ②原型定义:  

    public static IOrderedEnumerable<T> OrderBy<T,K>(

    this IEnumerable<T> source,

    Func<T,K> keySelector,

    IComparer<K> comparer);

  (3)原型说明:两个方法原型都是接收一个输入序列参数source和一个方法委托参数keyselector,返回一个类型为IOrderedEnumerable<T>的集合对象,而IOrderedEnumerable<T>接口是实现了IEnumerable<T>接口。OrderBy操作符把输入序列中的每一个元素作为参数传递给委托keyselector,接着委托keyselector根据传入类型为T的输入元素,返回一个类型为K的对象。区别在于前者是对象K实现了IComparable<K>泛型接口,实现了此接口对象就可以进行排序了。而后者则直接用一个类型为IComparer<K>的参数来用于排序;  

  (4)示例验证

①自定义字符串长度比较类(实现接口IComparer<T>):

OrderBy操作符
 1     public class StrLengthComparer:IComparer<string>
2 {
3 //实现IComparer<T>接口方法
4 public int Compare(string str1, string str2)
5 {
6 if (str1.Length > str2.Length)
7 return 1;
8 else if (str1.Length < str2.Length)
9 return -1;
10 else
11 return 0;
12 }
13 }

②调用操作符OrderBy:

View Code
 1         static void Main(string[] args)
2 {
3 //定义数据源
4 string[] array = new string[] {"Hello","Linq","To","Object","!" };
5
6 //OrderBy第一个原型
7 Console.WriteLine("调用OrderBy操作符第一个方法原型:");
8 Console.WriteLine("--------------------------------");
9
10 var items13 = array.OrderBy(str => str.Length);
11
12 Console.WriteLine("根据数组中字符串的长度进行顺序排序:");
13 foreach (var str in items13)
14 {
15 Console.WriteLine(str);
16 }
17
18 Console.WriteLine("****************************************");
19
20 //OrderBy第二个原型
21 Console.WriteLine("调用OrderBy操作符第二个方法原型:");
22 Console.WriteLine("--------------------------------");
23
24 //定义一个字符串长度比较的辅助对象
25 StrLengthComparer slc = new StrLengthComparer();
26
27 var items14 = array.OrderBy(str=>str,slc);
28
29 Console.WriteLine("根据数组中字符串的长度进行顺序排序(使用IComparer<T>辅助对象):");
30 foreach (var str in items14)
31 {
32 Console.WriteLine(str);
33 }
34
35 Console.Read();
36 }

结果

  10.OrderByDescending操作符

  (1)作用:用于对输入序列中的元素基于一个委托方法的返回值进行逆序排序;

  (2)方法原型

    ①原型定义:

    public static IOrderedEnumerable<T> OrderByDescending<T,K>(

    this IEnumerable<T> source,

    Func<T,K> keySelector)

    where K:IComparable<K>;

    ②原型定义:  

    public static IOrderedEnumerable<T> OrderByDescending<T,K>(

    this IEnumerable<T> source,

    Func<T,K> keySelector,

    IComparer<K> comparer); 

  (3)原型说明:操作符OrderByDescending原型定义和操作符OrderBy相同,实现的原理也一样,只不过OrderByDescending是逆序排序,而OrderBy是顺序排序罢了;

  (4)示例验证

OrderByDescending操作符
 1         static void Main(string[] args)
2 {
3 //定义数据源
4 string[] array = new string[] {"Hello","Linq","To","Object","!" };
5
6 //OrderByDescending第一个原型
7 Console.WriteLine("调用OrderByDescending操作符第一个方法原型:");
8 Console.WriteLine("--------------------------------");
9
10 var items15 = array.OrderByDescending(str => str.Length);
11
12 Console.WriteLine("根据数组中字符串的长度进行逆序排序:");
13 foreach (var str in items15)
14 {
15 Console.WriteLine(str);
16 }
17
18 Console.WriteLine("****************************************");
19
20 //OrderByDescending第二个原型
21 Console.WriteLine("调用OrderByDescending操作符第二个方法原型:");
22 Console.WriteLine("--------------------------------");
23
24 //定义一个字符串长度比较的辅助对象
25 StrLengthComparer slc1 = new StrLengthComparer();
26
27 var items16 = array.OrderByDescending(str => str, slc1);
28
29 Console.WriteLine("根据数组中字符串的长度进行逆序排序(使用IComparer<T>辅助对象):");
30 foreach (var str in items16)
31 {
32 Console.WriteLine(str);
33 }
34
35 Console.Read();
36 }

结果

  11.ThenBy操作符

  (1)作用:用于对操作符OrderBy或OrderByDescending返回的序列再次按照指定的条件进行顺序排序;

  (2)方法原型

    ①原型定义:

    public static IOrderedEnumerable<T> ThenBy<T,K>(

    this IOrderedEnumerable<T> source,

    Func<T,K> keySelector)

    where K:IComparable<K>;

    ②原型定义:  

    public static IOrderedEnumerable<T> ThenBy<T,K>(

    this IOrderedEnumerable<T> source,

    Func<T,K> keySelector,

    IComparer<K> comparer); 

  (3)原型说明:这两个方法原型和之前的操作符OrderByDescending和操作符OrderBy基本相同,唯一的区别在于ThenBy接收的第一个序列参数类型是IOrderedEnumerable<T>,而非IEnumerable<T>,但IOrderedEnumerable<T>接口是实现了接口IEnumerable<T>的。所以从第一个参数类型也能看出ThenBy操作符是基于操作符OrderByDescending和操作符OrderBy的结果再次进行排序

  (4)示例验证:  

OrderBy操作符
 1         static void Main(string[] args)
2 {
3 //定义数据源
4 string[] array = new string[] {"Hello","Linq","To","Object","!" };
5
6 //ThenBy第一个原型
7 Console.WriteLine("调用ThenBy操作符第一个方法原型:");
8 Console.WriteLine("--------------------------------");
9
10 var items17 = array.OrderBy(str => str.Length).ThenBy(str => str);
11
12 Console.WriteLine("先根据数组中字符串的长度进行顺序排序,长度相同的,再根据字符串ASCII码进行顺序排序:");
13 foreach (var str in items17)
14 {
15 Console.WriteLine(str);
16 }
17
18 Console.WriteLine("****************************************");
19
20 //ThenBy第二个原型
21 Console.WriteLine("调用ThenBy操作符第二个方法原型:");
22 Console.WriteLine("--------------------------------");
23
24 //定义一个字符串长度比较的辅助对象
25 StrLengthComparer slc2 = new StrLengthComparer();
26
27 var items18 = array.OrderBy(str => str).ThenBy(str=>str,slc2);
28
29 Console.WriteLine("先根据数组中字符串的ASCII码进行顺序排序,ASCII码号相同的,再根据字符串长度进行顺序排序(使用IComparer<T>辅助对象):");
30 foreach (var str in items18)
31 {
32 Console.WriteLine(str);
33 }
34
35 Console.Read();
36 }

结果

  12.ThenByDescending操作符

  (1)作用:用于对操作符OrderBy或OrderByDescending返回的序列再次按照指定的条件进行逆序排序;

  (2)方法原型

    ①原型定义:

    public static IOrderedEnumerable<T> ThenByDescending<T,K>(

    this IOrderedEnumerable<T> source,

    Func<T,K> keySelector)

    where K:IComparable<K>;

    ②原型定义:  

    public static IOrderedEnumerable<T> ThenByDescending<T,K>(

    this IOrderedEnumerable<T> source,

    Func<T,K> keySelector,

    IComparer<K> comparer); 

  (3)原型说明:操作符ThenByDescending和ThenBy的原型定义相同,方法实现的原理也一样,只不过ThenByDescending操作符是逆序排序,而ThenBy是顺序排序;

  (4)示例验证

ThenByDescending操作符
 1         static void Main(string[] args)
2 {
3 //定义数据源
4 string[] array = new string[] {"Hello","Linq","To","Object","!" };
5
6 //ThenByDescending第一个原型
7 Console.WriteLine("调用ThenByDescending操作符第一个方法原型:");
8 Console.WriteLine("--------------------------------");
9
10 var items19 = array.OrderByDescending(str => str.Length).ThenByDescending(str => str);
11
12 Console.WriteLine("先根据数组中字符串的长度进行逆序排序,长度相同的,再根据字符串ASCII码进行逆序排序:");
13 foreach (var str in items19)
14 {
15 Console.WriteLine(str);
16 }
17
18 Console.WriteLine("****************************************");
19
20 //ThenByDescending第二个原型
21 Console.WriteLine("调用ThenByDescending操作符第二个方法原型:");
22 Console.WriteLine("--------------------------------");
23
24 //定义一个字符串长度比较的辅助对象
25 StrLengthComparer slc3 = new StrLengthComparer();
26
27 var items20 = array.OrderByDescending(str => str).ThenByDescending(str => str, slc3);
28
29 Console.WriteLine("先根据数组中字符串的ASCII码进行逆序排序,ASCII码号相同的,再根据字符串长度进行逆序排序(使用IComparer<T>辅助对象):");
30 foreach (var str in items20)
31 {
32 Console.WriteLine(str);
33 }
34
35 Console.Read();
36 }

结果

  13.Reverse操作符

  (1)作用:用于生成一个与输入序列中的元素相同,但元素排列顺序相反的新序列;

  (2)方法原型

    public static IEnumerable<T> Reverse<T>(

    this  IEnumerable<T> source);

  (3)原型说明:Reverse操作符接收一个序列对象source,并把source中的元素进行相反排列,并返回排列后内容相同的新序列;

  (4)示例验证

Reverse操作符
 1         static void Main(string[] args)
2 {
3 //定义数据源
4 string[] array = new string[] {"Hello","Linq","To","Object","!" };
5
6 Console.WriteLine("调用Reverse操作符:");
7 Console.WriteLine("--------------------------------");
8
9 Console.WriteLine("相反排列之前字符串顺序:");
10 foreach (var str in array)
11 {
12 Console.WriteLine(str);
13 }
14
15 var items21 = array.Reverse();
16
17 Console.WriteLine("相反排列之后字符串顺序:");
18 foreach (var str in items21)
19 {
20 Console.WriteLine(str);
21 }
22
23 Console.Read();
24 }

结果

作者: Rookie_J

推荐.NET配套的通用数据层ORM框架:CYQ.Data 通用数据层框架
新浪微博粉丝精灵,刷粉丝、刷评论、刷转发、企业商家微博营销必备工具"