C# LINQ详解.docx

上传人:b****8 文档编号:10814368 上传时间:2023-02-23 格式:DOCX 页数:53 大小:49.28KB
下载 相关 举报
C# LINQ详解.docx_第1页
第1页 / 共53页
C# LINQ详解.docx_第2页
第2页 / 共53页
C# LINQ详解.docx_第3页
第3页 / 共53页
C# LINQ详解.docx_第4页
第4页 / 共53页
C# LINQ详解.docx_第5页
第5页 / 共53页
点击查看更多>>
下载资源
资源描述

C# LINQ详解.docx

《C# LINQ详解.docx》由会员分享,可在线阅读,更多相关《C# LINQ详解.docx(53页珍藏版)》请在冰豆网上搜索。

C# LINQ详解.docx

C#LINQ详解

C#LINQ详解

(一)

原文标题:

HowdoesitworkinC#?

-Part3(C#LINQindetail),作者:

Mohammand ARahman.

 

目录 

LINQ 基础 

扩展方法-幕后的工作 

扩展方法列表 

WhereandSelect 

All 

Average 

Concat 

Contains 

Count 

DefaultIfEmpty 

Distinct 

ElementAt 

Empty 

Except 

First 

FirstOrDefault 

Union 

Intersect 

Last 

LastOrDefault 

LongCount 

Max 

Min 

OfType 

Range 

Repeat 

Reverse 

Single 

Skip 

SkipWhile 

Sum 

ThenBy 

ToArray 

ToDictionary 

ToList 

Zip 

LINQ基础介绍 

         在.NET中,任何数据结构都是由在mscorlib.dll中System.Collections.Generic命名空间下的Ienumerable接口得到的. 映射可以访问所有的定义在System.Core.dll中System.Linq命名空间下的枚举类.这个枚举类是定义在System.Core.dll中System.Linq命名空间下的一个静态非可继承类.这个枚举类的定义如下:

 

.classpublicabstractautoansisealedbeforefieldinitSystem.Linq.Enumerableextends[mscorlib]System.Object

这个静态枚举类是对Ienumerable接口中不同扩展方法的一个封装.例如下面的例子:

 

publicstaticboolContains

thisIEnumerablesource,TSourcevalue)

{/*coderemoved*/}

publicstaticintCount

thisIEnumerablesource)

{/*coderemoved*/}

publicstaticIEnumerableDistinct

thisIEnumerablesource,IEqualityComparercomparer)

{/*coderemoved*/}

//andmanymore

扩展方法介绍 

WhereandSelect 

Where 和Select是两个定义在Ienumerable接口中非常重要的方法.它们的定义如下:

 

publicstaticIEnumerableWhere(thisIEnumerablesource,Funcpredicate)

publicstaticIEnumerableWhere(thisIEnumerablesource,Funcpredicate)

所以任何来源于Ienumerable接口的数据结构都能访问这个方法,例如List类.List类实现了Ienumerable接口,它的定义如下:

 

publicclassList:

IList,ICollection,IEnumerable,IList,ICollection, Ienumerable 

那么来让我们看一个关于Where和Select的例子. 

1usingSystem;

2

3usingSystem.Collections;

4

5usingSystem.Collections.Generic;

6

7usingSystem.Linq;

8

9

10

11namespaceChapter_5

12

13{

14

15classProgram

16

17{

18

19staticvoidMain(string[]args)

20

21{

22

23IListnumbers=newList()

24

25{

26

27"One","Two","Three","Four",

28

29"Five","Six","Seven"

30

31};

32

33

34

35varnumbersLengthThree=

36

37numbers.Where(x=>x.Length==3).Select(x=>x).ToList();

38

39

40

41numbersLengthThree.ForEach(x=>Console.WriteLine(x));

42

43}

44

45}

46

47}

上面的代码会产生一个string类型的列表(列表中是数字)存储在List中,上面的程序会找出在这些项中字符总数是3的并且将结果存储到另外一个新的列表中.最后在控制台中打印出这些数字.这个程序输出的结果如下:

 

One 

Two 

Six 

让我们做一个研究去找出它是如何工作的.在上面的例子中最重要的代码是numbers.Where(x=>x.Length==3).Select(x=>x).ToList().下边的图表会为我们解释整个的执行过程. 

通过上面的图表我们可以知道CLR伴随着MulticastDelegate实例(持有着关于

b_1方法的信息)将数字列表作为输入参数传递到Where方法,其中
b_1创建于匿名函数(x=>x.Length==3).通过Where方法它会返回一个WhereListIterator迭代器的实例,这个实例将会作为输入参数传递到Select子句中,伴随着另外一个MulticastDelegate实例(持有着关于
b_2方法的信息),
b_2通过匿名方法(x=>x)创建。

Select方法将根据输入内容实例化相关的迭代器。

在这种情况下,它会实例化出WhereSelectListIterator迭代器。

这个迭代器将作为输入参数传递到ToList()方法中。

此方法最终通过循环遍历对原始列表进行处理并得到一个基于过滤条件的新列表。

 

 

All 

这个方法确定是否所有元素序列都满足某种条件,如果每一个元素都可以满足设定的特殊条件或者它是空,则方法返回true,否则返回false。

方法定义如下:

 

publicstaticboolAll(thisIEnumerablesource,Funcpredicate)

 

这个方法被用在判断是否一个元素序列满足某种条件。

序列中的每一个元素都会经过判断。

在下面的程序中,我创建了一个包含One、Two、Three等项目的List实例,下面的程序将找出在这个序列中是否包含不少于3个字符的元素。

 

1usingSystem;

2

3usingSystem.Collections;

4

5usingSystem.Collections.Generic;

6

7usingSystem.Linq;

8

9

10

11namespaceChapter_5

12

13{

14

15classProgram

16

17{

18

19staticvoidMain(string[]args)

20

21{

22

23IListnumbers=newList()

24

25{

26

27"One","Two","Three","Four",

28

29"Five","Six","Seven"

30

31};

32

33

34

35if(numbers.All(x=>x.Length>=3))

36

37Console.WriteLine("Allnumbershaveatleastthreecharacters.");

38

39}

40

41}

42

43}

 

上面的程序将会输出:

Allnumbershaveatleastthreecharacters. 

因为All方法都将匹配序列中的元素对于指定的条件是否有效。

它的工作原理如下图:

 

从上面的图表我们可以知道CLR会通过数字列表作为输入参数传递到All()中,伴随着MulticasDelegate类的实例(这个实例通过匿名函数(x=>x.Length>=3)来创建)。

在All()方法中,CLR将通过指定的条件找出序列中的每一个元素是否满足条件。

 

 

Any 

这个方法确定序列中的元素是否存在或者满足某种特定的条件。

方法定义如下:

 

publicstaticboolAny(thisIEnumerablesource)

publicstaticboolAny(thisIEnumerablesource,Funcpredicate)

 

上面的两个方法将会执行下面的情况:

 

第一种重载会找出元素序列是否包含元素,第二种重载将会找出序列中是否有满足条件的元素。

我写了一个小程序去解释这两种方法工作的细节。

 

1usingSystem;

2

3usingSystem.Collections;

4

5usingSystem.Collections.Generic;

6

7usingSystem.Linq;

8

9

10

11namespaceChapter_5

12

13{

14

15classProgram

16

17{

18

19staticvoidMain(string[]args)

20

21{

22

23IListnumbers=newList()

24

25{

26

27"One","Two","Three","Four",

28

29"Five","Six","Seven"

30

31};

32

33

34

35if(numbers.Any())

36

37Console.WriteLine("Thesequencecontainsitem.");

38

39

40

41if(numbers.Any(x=>x.Length>=3))

42

43Console.WriteLine("Thesequencecontainsatleastaitemwhichhasthreeormorecharacters");

44

45

46

47}

48

49}

50

51}

 

上面的程序将会做如下输出:

 

Thesequencecontainsitem. 

Thesequencecontainsatleastaitemwhichhasthreeormorecharacters 

Pressanykeytocontinue... 

 

Average 

Average方法会计算在序列中的数字的平均值。

这个方法的定义如下:

 

publicstaticdoubleAverage(thisIEnumerablesource)

publicstaticdecimalAverage(thisIEnumerablesource,Funcselector)

 

下面是一个关于Average方法的列子:

 

1usingSystem;

2

3usingSystem.Collections;

4

5usingSystem.Collections.Generic;

6

7usingSystem.Linq;

8

9

10

11namespaceChapter_5

12

13{

14

15classProgram

16

17{

18

19staticvoidMain(string[]args)

20

21{

22

23IListnumbers=newList()

24

25{

26

271,2,3,4,5,6,7,8,9,10

28

29};

30

31

32

33Console.WriteLine("Averageofthenumbers:

{0}",numbers.Average());

34

35

36

37Console.WriteLine("Averageoftheoriginalnumbersx2:

{0}",

38

39numbers.Average((x=>x*2)));

40

41

42

43}

44

45}

46

47}

 

上面的程序将会做如下输出:

 

Averageofthenumbers:

5.5 

Averageoftheoriginalnumbersx2:

11 

Pressanykeytocontinue... 

 

Concat 

这个方法的作用是连接(拼接)两个序列.这个方法通过"延迟执行"(deferredexecution)来执行.它的返回值是包含需要执行特定操作所有信息的迭代器类型的一种实例.在C#中,对象在调用它的GetEnumerator方法或者使用foreach语句时才会执行Concat方法. 

Concat(Ienumerable,Ienumerable)方法不同于Union(),因为Concat(Ienumerable,Ienumerable)方法会返回序列中所有的原始元素,而Union则返回序列中不重复(独一无二)的元素.方法定义如下:

 

publicstaticIEnumerableConcat(thisIEnumerablefirst,IEnumerablesecond)

 

下面的程序将告诉我们怎样使用Concat方法. 

1usingSystem;

2

3usingSystem.Collections;

4

5usingSystem.Collections.Generic;

6

7usingSystem.Linq;

8

9

10

11namespaceChapter_5

12

13{

14

15classProgram

16

17{

18

19staticvoidMain(string[]args)

20

21{

22

23IListlistOne=newList()

24

25{

26

271,2,3,4,5

28

29};

30

31

32

33IListlistTwo=newList()

34

35{

36

376,7,8,9,10

38

39};

40

41

42

43varresult=listOne.Concat(listTwo).ToList();

44

45result.ForEach(x=>Console.WriteLine(x));

46

47

48

49

50

51}

52

53}

54

55}

 

上面的程序将会做如下输出:

 

10 

Pressanykeytocontinue... 

Concat方法的工作原理如下图所示:

 

从上图我们可以知道CLR通过将listOne和listTwo作为输入参数传递到Concat方法中,并且从Concat方法中返回一个ConcatIterator实例作为输出参数给这个方法的调用者.虽然这将通过延迟执行模式来执行,但是ToList()方法也会通过listOne和listTwo的ConcatIterator类的执行逻辑来开始处理并得到最终的集合。

 

 

Contains 

这个方法用来判断在一个序列(集合)中是否存在一个特殊的元素.这个方法有两种重载方式,第一种是通过默认的比较器来判断序列(集合)中是否有特殊的元素,另外一种是通过自定义IEqualityComparer来确定序列(集合)中是否有特殊的元素.它们的方法定义如下:

 

publicstaticboolContains(thisIEnumerablesource,TSourcevalue)

publicstaticboolContains(thisIEnumerablesource,TSourcevalue,IEqualityComparercomparer)

 

这个方法将会查找在集合中是否有一个特殊的值存在.为了解释这个方法我写了一个小程序:

 

1usingSystem;

2

3usingSystem.Collections;

4

5usingSystem.Collections.Generic;

6

7

8

9namespaceChapter_5

10

11{

12

13classProgram

14

15{

16

17staticvoidMain(string[]args)

18

19{

20

21IListlistOne=newList()

22

23{

24

251,2,3,4,5

26

27};

28

29

30

31varresultAsTrue=listOne.Contains

(2);

32

33varresultAsFalse=listOne.Contains(200);

34

35Console.WriteLine("{0}\n{1}",resultAsTrue,resultAsFalse);

36

37}

38

39}

40

41}

 

上面的程序将会做如下输出:

 

True 

False 

Pressanykeytocontinue.. 

因此,在上述程序中当编译器找到Contains方法的第一种重载方式,它会执行如下步骤:

CLR会通过Contains方法在集合中查找一个特定的值.这种查找会有两个方向,一种是如果输入参数是一个空值(nullvalue),它(CLR)会在集合中循环遍历是空值的项,如果其中一项是空值,就返回true,反之返回false.另一种情况是当不是空值的时候,CLR会对集合中的项依次进行比较,根据匹配值返回一个布尔类型作为应答. 

Contains方法的一个近似代码如下所示:

 

1publicboolContains(Titem)

2

3{

4

5if(item==null)

6

7{

8

9for(intj=0;j

10

11{

12

13if(this._items[j]==null)

14

15{

16

17returntrue;

18

19}

20

21}

22

23returnfalse;

24

25}

26

27

28

29EqualityComparercomparer=EqualityComparer.Default;

30

31for(inti=0;i

32

33{

34

35if(comparer.Equals(this._items[i],item))

36

37{

38

39returntrue;

40

41}

42

43}

44

45returnfalse;

46

47}

 

 

Count 

Count方法将返回序列(集合)中元素的个数.这个方法的定义如下:

 

publicstaticintCount(thisIEnumerablesource)

publicstaticintCount(thisIEnumerablesource,Funcpredicate)

 

上面的两个重载方法将会做如下操作.第一种重载直接返回序列(集合)中元素的个数,第二种重载返回一个数字,表示在

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 解决方案 > 学习计划

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1