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子句。回顾上一章内容的示例:

var result = from n in names where n.StartsWith("s") select n;

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

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

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

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

2.2.1 用方法语法排序

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

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

或者:

var result = 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方法上来实现的。例如要实现上一章示例五的功能,代码如下:

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

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

常见错误:

var result=list.Select(stu=>new stu.Name,stu.Age,

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

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

var result=list.Select(stu=>new stu.Name,stu.Age,

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

2.2.3 AnyAll

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

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

bool anyStu = list.Any(stu => stu.Sex == "");

if (anyStu)

{

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

}

else

{

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

}

bool allStu = list.All(stu => stu.Sex == "");

if (allStu)

{

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

}

else

{

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

}

运行结果:

2.2.4 ThenBy -----多级排序

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

var result=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.5 TakeSkip

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

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

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

var result = list.OrderBy(stu => stu.Age);

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

foreach (var stu in result.Take(2))

{

    Console.WriteLine(stu);

}

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

foreach (var stu in result.Skip(2))

{

    Console.WriteLine(stu);

}

运行结果:

2.2.6 FirstFirstOrDefault

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()也是一个集运算符。

下面定义一个分数类

class Score

    {

        public int ID{get;set;}

        public int score{get;set;}

}

示例代码:

static void Main(string[] args)

{

    List<Student> list = new List<Student>{

        new Student{ID=1,Name="zhangsan",Sex="", Age=18,Class=50},

        new Student{ID=2,Name="lisi",Sex="", Age=18,Class=50},

        new Student{ID=3,Name="wuangwu",Sex="", Age=20,Class=51},

        new Student{ID=4,Name="zhaoliu",Sex="", Age=20,Class=52},

        new Student{ID=5,Name="zhouqi",Sex="", Age=21,Class=52},

        new Student{ID=6,Name="wangba",Sex="", Age=20,Class=52}

    };

    List<Score> Scores = new List<Score> {

        new Score {ID=1,score=80},

        new Score {ID=2,score=90},

        new Score {ID=3,score=70},

        new Score {ID=4,score=60},

        new Score {ID=5,score=50},

        new Score {ID=7,score=40}};

    var student = from s in list select s.ID;

    var score = from scr in Scores select scr.ID;

    var stuWithScore = student.Intersect(score);

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

    foreach (var item in stuWithScore)

    {

        Console.WriteLine(item);

    }

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

    var scoreNoStu = score.Except(student);

    foreach (var item in scoreNoStu)

    {

        Console.WriteLine(item);

    }

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

    var allID = score.Union(student);

    foreach (var item in allID)

    {

        Console.WriteLine(item);

    }

}

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

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

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

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

2.2.8 Join查询

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

var result = from stu in list join scr in Scores on stu.ID equals scr.ID select new { stu.ID, stu.Name, scr.score };

    foreach (var ss in result)

    {

        Console.WriteLine(ss);

    }

阅读更多
个人分类: Linq学习
想对作者说点什么? 我来说一句

LINQ学习文档

2013年01月17日 195KB 下载

Linq To Sql

2012年04月10日 240KB 下载

LINQ 查询简介

2012年02月07日 68KB 下载

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭