LINQ简介(二)

LINQ简介(二)

------Linq方法语法和Lambda表达式

2.1λ表达式

Lambda表达式用来实现一个匿名方法,其语法为:

(参数列表)=>语句或语句块

这是一个简单的Lambda表达式:n=>n<1000;

运算符“=>”称为λ表达式。这个表达式定义了一个方法(函数),其参数是n,如果n小于1000,该方法就返回ture,否则返回false。该方法是一个没有名称的匿名方法,仅在把λ表达式传给Linq方法时使用。

2.2λ表达式在Linq中的使用

用Linq完成同一任务有多种方式,但通常需要通过编程来实现。如上一章内容是使用Linq查询语法编写的。本章内容将重点介绍Linq的方法语法。

Linq拥有一系列扩展方法,用于集合、数组、查询结果等对象,不在需要from…where…select子句。回顾上一章内容的示例:

varresult=fromninnameswheren.StartsWith("s")selectn;

现在可以用方法语法来实现:

varresult=names.Where(n=>n.StartsWith("s"));

C#编译器把λ表达式编译成一个匿名方法,where()在names数组中的每一个元素上执行这个方法。如果λ表达式给某个元素返回true,该元素就包含在Where()返回的结果集中。

查询语法是Linq中编写查询的首选方式,但是一定要基本了解方法语法,因为一些Ling功能不能通过查询语法来使用,或者说使用方法语法比较简单。

2.2.1用方法语法排序

对刚才的查询结果排序可以使用如下语句:

varresult=names.OrderBy(n=>n).Where(n=>n.StartsWith("s"));

或者:

varresult=names.Where(n=>n.StartsWith("s")).OrderBy(n=>n);

方法调用的顺序不是固定的,只要Linq方法返回值为IEnumerable类型即可,可以按照容易理解的方式来使用。此规则适合于以后讲到的其他方法。

OrderBy()方法需要传入一个λ表达式用来告诉它用于排序的方法是什么,我们传送了最简单的λ表达式n=>n,因为只需要按照元素本身排序。还可以向上一章所讲那样按照最后一个字母进行排序,传给OrderBy()方法一个这样的表达式:n=>n.Substring(n.Length-1)

为了给元素逆序排序,可以调用OrderByDescending()方法,使用方法和OrderBy()相同。

2.2.2投射的方法语法

投射查询的方法语法版本是通过把Linq方法Select()的调用关联到我们调用的其他Linq方法上来实现的。例如要实现上一章示例五的功能,代码如下:

varresult=list.Where(stu=>stu.Age==18).Select(stu=>new{stu.Name,stu.Age,stu.Class});

Select()方法用于方法语法的投射。

常见错误:

varresult=list.Select(stu=>newstu.Name,stu.Age,

stu.Class}).Where(stu=>stu.Sex==’男’);

虽说方法的调用顺序不固定,但根据查询的特性,不适用与上面的查询。因为Sex属性并不包含在Select()投射创建的匿名类型(stu.Name,stu.Age,stu.Class)中,所以上述代码会在Where()方法上得到一个编译错误---匿名类型不包含Sex的定义。改成如下写法是正确的。

varresult=list.Select(stu=>newstu.Name,stu.Age,

stu.Class}).Where(stu=>stu.Class==’50’);

2.2.3Any和All

我们常常需要的另一类查询是确定数据是否满足某个条件,或者确保所有的数据都满足某个条件。例如,需要确定某个产品是否没有货了(库存为0)。

Linq提供了两个布尔方法:Any()和All(),它们可以快速确定对于数据而言,某个条件是true还是false。如下面示例所示:

boolanyStu=list.Any(stu=>stu.Sex=="男");

if(anyStu)

{

Console.WriteLine("学员中有男同学");

}

else

{

Console.WriteLine("学员中没有男同学");

}

boolallStu=list.All(stu=>stu.Sex=="男");

if(allStu)

{

Console.WriteLine("学员中全部是男同学");

}

else

{

Console.WriteLine("学员中不全是男同学");

}

运行结果:

2.2.4ThenBy-----多级排序

使用方法语法进行多级排序时,后台的操作比较复杂,它使用了ThenBy()和OrderBy()方法。示例代码如下:

varresult=list.OrderBy(stu=>stu.Class)

.ThenBy(stu=>stu.Age)

.ThenBy(stu=>stu.Name)

.Select(stu=>new{stu.Name,stu.Age,stu.Class});

多字段列表可以用在查询语法的OrderBy子句中。但在方法语法中第一项排序字段必须使用OrderBy()方法,随后使用ThenBy()方法。

如果第一个字段是以降序排序,需要使用OrderByDescending()方法,其他字段降序排序需要使用ThenByDescending()方法。

2.2.5Take和Skip

Take()方法对应SQL语句中的Top运算符。

Take()方法相反的是Skip()方法,它可以跳过前n个结果,返回剩余的结果。

Take()和Skip()在Linq中成为分区运算符。

varresult=list.OrderBy(stu=>stu.Age);

Console.WriteLine("年龄最小的两名学员是:");

foreach(varstuinresult.Take(2))

{

Console.WriteLine(stu);

}

Console.WriteLine("其他学员依次为:");

foreach(varstuinresult.Skip(2))

{

Console.WriteLine(stu);

}

运行结果:

2.2.6First和FirstOrDefault

First()方法用来查找集合中第一个匹配的元素,如果没有找到匹配的结果则会引发一个异常。可以使用FirstOrDefault()方法避免异常的发生。

示例代码:

Console.WriteLine("姓名为lisi的同学信息:");

Console.WriteLine(list.First(stu=>stu.Name=="lisi"));

Console.WriteLine("姓名为hanjiu的同学信息:");

Console.WriteLine(list.FirstOrDefault(stu=>stu.Name=="hanjiu"));

FirstOrDefault()方法若没有找到则返回有一个空。

2.2.7集运算符

Linq提供了标准的集运算符,如Union()和Intersect(),对查询结果执行操作,上一章的Distinct()也是一个集运算符。

下面定义一个分数类

classScore

{

publicintID{get;set;}

publicintscore{get;set;}

}

示例代码:

staticvoidMain(string[]args)

{

List<Student>list=newList<Student>{

newStudent{ID=1,Name="zhangsan",Sex="男",Age=18,Class=50},

newStudent{ID=2,Name="lisi",Sex="男",Age=18,Class=50},

newStudent{ID=3,Name="wuangwu",Sex="男",Age=20,Class=51},

newStudent{ID=4,Name="zhaoliu",Sex="男",Age=20,Class=52},

newStudent{ID=5,Name="zhouqi",Sex="女",Age=21,Class=52},

newStudent{ID=6,Name="wangba",Sex="女",Age=20,Class=52}

};

List<Score>Scores=newList<Score>{

newScore{ID=1,score=80},

newScore{ID=2,score=90},

newScore{ID=3,score=70},

newScore{ID=4,score=60},

newScore{ID=5,score=50},

newScore{ID=7,score=40}};

varstudent=fromsinlistselects.ID;

varscore=fromscrinScoresselectscr.ID;

varstuWithScore=student.Intersect(score);

Console.WriteLine("有成绩的学员编号为:");

foreach(variteminstuWithScore)

{

Console.WriteLine(item);

}

Console.WriteLine("未知学员的成绩编号为:");

varscoreNoStu=score.Except(student);

foreach(variteminscoreNoStu)

{

Console.WriteLine(item);

}

Console.WriteLine("所有的编号为:");

varallID=score.Union(student);

foreach(variteminallID)

{

Console.WriteLine(item);

}

}

Intersect()查找在Student结果中有成绩的学员编号,

Except()用于查找没有匹配学员的成绩编号

Union()预算法用于查找两个结果的并集,要删除重复项

集运算符要求集成员有相同的类型才能确保得到希望的结果。

2.2.8Join查询

Join可以用一个查询搜索两个列表中相关的数据,用关键字段把结果连接起来。类似于SQLjoin(内连接)操作。如:

varresult=fromstuinlistjoinscrinScoresonstu.IDequalsscr.IDselectnew{stu.ID,stu.Name,scr.score};

foreach(varssinresult)

{

Console.WriteLine(ss);

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值