在C#中利用Linq进行一些集合的操作是十分方便的,传统的一些编程方式自然也能相同的功能,不过使用Linq更加的优雅。
C#的一些高级语言特性确实令人着迷。
我这边就直接通过几个例子来展现一下Linq的强大,就不说逐字逐句的扣语法了。
Linq之前:
在写Linq之前有几个C#新的知识点必须掌握才能学习它。
1.匿名对象:
学过Java的同学知道匿名对象的强大之处,一个接口可以直接通过new关键字来产生一个对象,在new的过程中可以指定需要override的方法,填加新的字段。
不过在C#中,Java的匿名对象被分为了两个知识点,一个是delegate,另一个就是现在要说的匿名对象,在C#中的匿名对象只能添加字段,而不能添加方法。
例子如下:
-
var psn =
new { name =
"小明" };
-
Console.WriteLine(psn.name);
因为只能添加字段,所以平时大家也不常用,可以说这个东西是专门为Linq准备的。
2.lambda表达式:
上面说了delegate,而delegate的创建方式有两种,一种是直接把类中的函数赋值进去,另一种是匿名函数,也就这边的lambda表达式了。
关于delegate实际上是一种将方法(函数)作为对象存储到变量中的一种技术,如果对这个不是很了解,建议写几个程序练习一下。
这边给出lambda和普通函数的对比:
-
static void Main_Delegate(string[] args)
-
{
-
Action method_lambda = () =>
-
{
-
Console.WriteLine(
"Hello");
-
};
-
-
Action method_normal = PrintHello;
-
-
method_lambda();
-
method_normal();
-
}
-
-
static void PrintHello()
-
{
-
Console.WriteLine(
"Hello");
-
}
正式Linq的练习:
首先在写之前,需要知道Linq其实就是对集合提供类似于sql一般的操作。
我们准备好今天需要查询的数据:
-
class
Person
-
{
-
public
string name;
-
public
int age;
-
public override string ToString()
-
{
-
return
"name: " + name +
", age: " + age;
-
}
-
}
-
-
class
Course
-
{
-
public
string personName;
-
public
string name;
-
public
int score;
-
-
public override string ToString()
-
{
-
return
"name: " + name +
", score: " + score +
", personName: " + personName;
-
}
-
}
-
-
List<Person> list =
new List<Person>();
-
list.Add(
new Person(){ name =
"小明", age =
19});
-
list.Add(
new Person(){ name =
"小红", age =
17});
-
list.Add(
new Person(){ name =
"小强", age =
20});
-
-
List<Course> list2 =
new List<Course>();
-
list2.Add(
new Course(){ personName =
"小明", name =
"数学", score =
90});
-
list2.Add(
new Course(){ personName =
"小明", name =
"英语", score =
56});
-
list2.Add(
new Course(){ personName =
"小红", name =
"数学", score =
60});
-
list2.Add(
new Course(){ personName =
"小红", name =
"英语", score =
100});
一些人和他们本次考试的成绩。
1.马上来做第一个查询,查询所有年龄大于18岁的人:
-
from p
in list
-
where p.age >
18
-
select p
这就是一个最简单的查询了,需要记住的是每个查询都是以from ... in ...开头,select或group结尾。
Linq有两种表达形式,一种就是以上类似于sql的表达式,另一种是使用IEnumerable的扩展方法:
list.Where(p=>p.age>18);
效果是一样的,都属于Linq。这边再提一个方法,List的FindAll方法:
list.FindAll(p => p.age > 18);
通过以上的方式,返回的结果和上面两种方式是一模一样的,不过FindAll方法属于List,而上面两种Linq是基于IEnumerable接口的,所以我们知道了,Linq的集合接口的基础就是IEnumerable,只要实现了该接口的集合就能做Linq操作。
第一个说的可能比较多,下面就快了。
2.多集合查询,查询所有及格的课程对应的人:
-
from p
in list
-
from c
in list2
-
where c.personName == p.name && c.score >=
60
-
select
new{c, p}
-
-
list.SelectMany(c=>list2, (person, course) =>
new {person, course} )
-
.Where(x=>x.course.personName==x.person.name & x.course.score>=
60)
这边SelectMany将list和list2映射到一个新的匿名集合,这边我取名为x,而两个新的集合名分别为person和course。
3.使用Join代替多集合查询:
-
from p
in list
-
join c
in list2
on p.name
equals c.personName
-
where c.score >=
60
-
select
new { c, p }
-
-
list.Join(list2, p=>p.name, c=>c.personName, (p, c) =>
new { c, p })
-
.Where(x=>x.c.score >=
60)
跟上面的多集合查询效果是一样的,只不过就是把相等条件提取出来了而已。
4.使用into关键字,查询选课数量:
-
from p
in list
-
join c
in list2
on p.name
equals c.personName
-
into groups
-
select
new { p.name, count = groups.Count() }
-
-
list.GroupJoin(list2, p=>p.name, c=>c.personName, (p, cs)=>
new{p.name, count=cs.Count()})
通过from和join之后产生了一个大集合,而into将p为同一个的查询记录放到同一个集合groups中。
也就是将同一个人的课程放到groups集合中,调用groups.Count()自然是课程的数量
5.查询课程选修的人数:
-
from c
in list2
-
group c
by c.name
into cs
-
select
new {name=cs.Key, count=cs.Count()}
-
-
list2.GroupBy(c=>c.name).Select((cs)=>
new{name=cs.Key, count=cs.Count()})
使用group by关键字将课程名相同的放到一个集合中,原理跟上面查询是一样。
以上是几个基本的练习,感觉掌握了这些,面对大部分需求应该是没有问题的了,以后学到了新的还会继续补充。
6.从0遍历到99:
from i in Enumerable.Range(0, 99) select i
7.99重复10遍:
from i in Enumerable.Repeat(99, 10) select i
另一篇参考文章
https://www.cnblogs.com/dullfish/p/6101912.html