LINQ是一个用于操作集合的语法,它能够查询一个集合里的字段,并且能够分组、排序,除此之外还有其他的功能。它的语法规则和SQL语言非常相似。
在一个集合中,我们想要得到集合里满足特定条件下的集合,通常情况下我们会用foreach循环来获取里面的集合。
首先我们先定义两个集合
//武林高手集合
class MartialArtsMaster
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public string Menpai { get; set; }
public string Kungfu { get; set; }
public int Level { get; set; }
//重写ToString方法
public override string ToString()
{
return $"Id: {Id}, Name: {Name}, Age: {Age}, Menpai: {Menpai}, Kungfu: {Kungfu}, Level: {Level}";
}
}
//武学集合
class Kungfu
{
public int Id;
public string Name;
public int Power;
public override string ToString()
{
return $"Id: {Id}, Name: {Name}, Power: {Power}";
}
}
然后在主函数里new两个集合对象
static void Main(string[] args)
{
//初始化武林高手
var masterList = new List<MartialArtsMaster>()
{
new MartialArtsMaster() {Id = 1, Name = "黄蓉", Age = 18, Menpai = "丐帮", Kungfu = "打狗棒法", Level = 9},
new MartialArtsMaster() {Id = 2, Name = "洪七公", Age = 70, Menpai = "丐帮", Kungfu = "打狗棒法", Level = 10},
new MartialArtsMaster() {Id = 3, Name = "郭靖", Age = 22, Menpai = "丐帮", Kungfu = "降龙十八掌", Level = 10},
new MartialArtsMaster() {Id = 4, Name = "任我行", Age = 50, Menpai = "明教", Kungfu = "葵花宝典", Level = 1},
new MartialArtsMaster() {Id = 5, Name = "东方不败", Age = 35, Menpai = "明教", Kungfu = "葵花宝典", Level = 10},
new MartialArtsMaster() {Id = 6, Name = "林平之", Age = 23, Menpai = "华山", Kungfu = "葵花宝典", Level = 7},
new MartialArtsMaster() {Id = 7, Name = "岳不群", Age = 50, Menpai = "华山", Kungfu = "葵花宝典", Level = 8},
new MartialArtsMaster() {Id = 8, Name = "令狐冲", Age = 23, Menpai = "华山", Kungfu = "独孤九剑", Level = 10},
new MartialArtsMaster() {Id = 9, Name = "梅超风", Age = 23, Menpai = "桃花岛", Kungfu = "九阴真经", Level = 8},
new MartialArtsMaster() {Id = 10, Name = "黄药师", Age = 23, Menpai = "梅花岛", Kungfu = "弹指神通", Level = 10},
new MartialArtsMaster() {Id = 11, Name = "风清扬", Age = 23, Menpai = "华山", Kungfu = "独孤九剑", Level = 10}
};
//初始化武学
var KungfuList = new List<Kungfu>()
{
new Kungfu() {Id = 1, Name = "打狗棒法", Power = 90},
new Kungfu() {Id = 2, Name = "降龙十八掌", Power = 95},
new Kungfu() {Id = 3, Name = "葵花宝典", Power = 100},
new Kungfu() {Id = 4, Name = "独孤九剑", Power = 100},
new Kungfu() {Id = 5, Name = "九阴真经", Power = 100},
new Kungfu() {Id = 6, Name = "弹指神通", Power = 100}
};
}
查询
然后我们使用foreach循环来查询武学级别大于8的武林高手
//查询所有武学级别大于8的武林高手
var res = new List<MartialArtsMaster>();
foreach (var temp in masterList)
{
if (temp.Level > 8)
{
res.Add(temp);
}
}
但是使用LINQ能够使代码更加的简洁并且易懂
//使用LINQ查询
var res = from m in masterList //from后面设置查询的集合
where m.Level > 8 //where后面跟上查询的条件
select m.Name; //表示m的结果返回
我们使用扩展方法可以使它更加简洁,写一个方法来存储判断条件,每次要判断的时候就调用这个方法
//扩展方法
var res = masterList.Where(Test1);
//判断方法
bool Test1(MartialArtsMaster master)
{
if (master.Level > 8) return true;
return false;
}
但是写一个判断方法对我们来说,如果条件修改了,那这个方法也需要修改,这时候我们可以使用之前学的Lambda表达式,因为这个判断方法可以作为一个匿名方法,里面的方法体才是对我们有用的。
//Lambda表达式
var res = masterList.Where(m => m.Level > 8 && m.Menpai == "丐帮");
联合查询
前面几个方法都是对一个集合查询,我们还可以使用LINQ对两个集合进行联合查询
//LINQ联合查询
var res = from m in masterList
from k in Kungfu
where m.Kungfu == k.Name && k.Power >= 95
select m;
然后我们还是使用扩展方法和Lambda表达式来对代码进行优化
//扩展方法——LINQ联合查询
var res = masterList.SelectMany(m => KungfuList, (m, k) => new {master = m, Kungfu = k})
.Where(x => x.master.Kungfu == x.Kungfu.Name && x.Kungfu.Power > 95);
这里的代码使用了Func委托,我们可以在代码中查看SelectMany这个方法是如何使用的,否则很难理解这里代码的意思。
联合查询还有另外一种方法:join in集合联合查询
//join in集合联合查询
var res = from m in masterList
join k in KungfuList on m.Kungfu equals k.Name
where k.Power > 95
select new {master = m,Kungfu=k}; //表示将两个集合结合在一起成为一个新的集合然后返回该集合
排序
我们查询完结果后,可以对结果的某个字段进行排序,默认排序是从小到大,使用descending则倒序
//对查询结果进行排序orderby 倒序descending
var res = from m in masterList
where m.Level > 8 && m.Menpai == "丐帮"
//orderby m.Age descending //倒序
orderby m.Level,m.Age //按照多个字段排序,若前面的字段属性相同,再对第二个字段进行排序
select m;
代码优化之后
//扩展方法
var res = masterList.Where(m => m.Level > 8 && m.Menpai == "丐帮").OrderBy(m=>m.Age);
//按照多个字段排序
var res = masterList.Where(m => m.Level > 8 && m.Menpai == "丐帮").OrderBy(m => m.Level).ThenBy(m => m.Age);
扩展方法里的多个字段排序,只能使用ThenBy关键字,如果还是使用OrderBy关键字,则会在level排序之后,再根据Age再重新排序。
分组查询
查询完结果之后,我们可以对集合进行分组,只得到自己想要的结果,其余的字段可以忽略
//分组查询 into groups(按照功夫分类)
var res = from k in KungfuList
join m in masterList on k.Name equals m.Kungfu
into groups //分组关键字
orderby groups.Count()
//将master=m改成groups.Count()是因为分完组后,
//master就是作为组来输出了,不再以单个形式出现
select new {Kungfu = k, count = groups.Count()};
我们还可以根据集合里的某个字段进行分组
//按照自身字段分组 group
var res = from m in masterList
group m by m.Menpai
into g //将分组完的信息放入g中
select new { count = g.Count(), key = g.Key }; //key是指分组所根据的字段,在这里指Menpai这个字段
量词操作符
使用量词操作符我们可以判断这个集合里是否存在某个字段
//Any只需要其中一个字段相同就返回True
bool result = masterList.Any(m => m.Menpai == "丐帮");
//All需要全部字段都相同才返回True
bool result2 = masterList.All(m => m.Menpai == "丐帮");
Console.WriteLine(result);
Console.WriteLine(result2);
LINQ的方法还有很多,这些是最常用的,上面的代码得到的结果可以使用foreach遍历返回的集合来输出
foreach (var temp in res)
{
Console.WriteLine(temp);
}
LINQ不仅仅能够对集合进行操作,还能够对XML数据源、Sql Server进行操作,但是微软已不再更新对Sql的操作,所以推荐使用LINQ to Entitles。但是我们最经常使用的还是对内存中的集合的操作。