语言集成查询 (Language Integrated Query) 是一系列直接将查询功能集成到 C# 语言的技术统称,用于在所有基于.NET平台的变成语言中更加直接地声明跨越、过滤和投射操作的一种方式,标准查询操作允许查询作用于所有基于IEnumerable接口的源。
LINQ简单查询
using System;
using System.Linq;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
int[] scores = new int[] { 90, 91, 59, 55, 80 };
var x = from score in scores where score >= 60 orderby score descending select score;
foreach( var s in x)
{
Console.WriteLine(s);
}
Console.ReadLine();
}
}
}
函数
案例一
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
List<int> num1 = new List<int> { 1, 2, 3, 4, 5 };
List<int> num2 = new List<int> { 17, 18, 19, 20 };
var concat = num1.Concat(num2);
double average = concat.Average();
Console.WriteLine(average);
Console.ReadLine();
}
}
}
案例二
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
int[] scores = new int[] { 81, 90, 60, 55, 100 };
var c = from score in scores where score >= 60 select score;
Console.WriteLine(c.Count());
Console.WriteLine(c.Max());
Console.ReadLine();
}
}
}
LINQ子句
where子句
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
List<Student> students = new List<Student>()
{
new Student() {name="张三", age=22, telephone="1234567890"},
new Student() {name="张四", age=23, telephone="1234567891"},
new Student() {name="王五", age=21, telephone="1234567892"}
};
var query = from student in students
where student.name.Contains("张")
&& student.age > 21
select student;
foreach (var s in query)
{
Console.WriteLine("{0} - {1} - {2}", s.name, s.age, s.telephone);
}
Console.ReadLine();
}
}
public class Student
{
public string name { get; set; }
public int age { get; set; }
public string telephone { get; set; }
}
}
orderby 子句
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
List<Student> students = new List<Student>()
{
new Student() {name="张三", age=22, telephone="1234567890"},
new Student() {name="张四", age=23, telephone="1234567891"},
new Student() {name="王五", age=21, telephone="1234567892"}
};
var query = from student in students
where student.name.Contains("张")
&& student.age > 21
orderby student.age descending
select student;
foreach (var s in query)
{
Console.WriteLine("{0} - {1} - {2}", s.name, s.age, s.telephone);
}
Console.ReadLine();
}
}
public class Student
{
public string name { get; set; }
public int age { get; set; }
public string telephone { get; set; }
}
}
select 子句
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
List<Student> students = new List<Student>()
{
new Student() {name="张三", age=22, telephone="1234567890"},
new Student() {name="张四", age=23, telephone="1234567891"},
new Student() {name="王五", age=21, telephone="1234567892"}
};
// 替换
var query1 = from student in students
orderby student.age descending
select student.name.Replace("张四", "李四");
// 自定义方法
var query2 = from student in students
orderby student.age descending
select MyFunc(student.name);
// 匿名类型
var query3 = from student in students
orderby student.age descending
select new { name=student.name + "OK!", age=student.age+10};
// 对查询结果投影
var query4 = from student in students
orderby student.age descending
select new Student{ name = student.name, age = 25, telephone=""};
foreach (var s in query1)
{
Console.WriteLine(s);
}
foreach (var s in query2)
{
Console.WriteLine(s);
}
foreach (var s in query3)
{
Console.WriteLine(s.name + " " + s.age);
}
foreach (var s in query4)
{
Console.WriteLine(s.name + " " + s.age);
}
static string MyFunc(string s)
{
return s + "好!";
}
Console.ReadLine();
}
}
public class Student
{
public string name { get; set; }
public int age { get; set; }
public string telephone { get; set; }
}
}
多个from子句
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
List<Student> students = new List<Student>()
{
new Student() {name="张三", age=22, addr= new List<string>(){ "中国", "山东"}, scores=new List<int>{99, 100} },
new Student() {name="张四", age=23, addr= new List<string>(){ "中国", "山东"}, scores=new List<int>{99, 100}},
new Student() {name="王五", age=21, addr= new List<string>(){ "中国", "山东"}, scores=new List<int>{99, 100}}
};
var query1 = from student in students
from add in student.addr
from score in student.scores
orderby student.age descending
select new {newName = student.name, newAddr = add, nawSocre = score};
foreach(var s in query1)
{
Console.WriteLine(s);
}
Console.ReadLine();
}
}
public class Student
{
public string name { get; set; }
public int age { get; set; }
public List<string> addr { get; set; }
public List<int> scores { get; set; }
}
}
LINQ中的from子句中引用的数据源类型必须是IEnumerable、IEnumerable或一种派生类型(如IQueryable)类型。
如果一个数据源里面又包含一个或多个集合列表,可以使用复合的from子句查询。
group子句
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
List<Student> students = new List<Student>()
{
new Student() {name="张三", age=22, addr= new List<string>(){ "中国", "山东"}, scores=new List<int>{99, 100} },
new Student() {name="张四", age=23, addr= new List<string>(){ "中国", "山东"}, scores=new List<int>{99, 100}},
new Student() {name="王五", age=21, addr= new List<string>(){ "中国", "北京"}, scores=new List<int>{99, 100}}
};
var query = from student in students
group student by student.addr[1];
foreach(var group in query)
{
Console.WriteLine(group.Key);
foreach(var s in group)
{
Console.WriteLine(" "+s.name);
}
}
Console.ReadLine();
}
}
public class Student
{
public string name { get; set; }
public int age { get; set; }
public List<string> addr { get; set; }
public List<int> scores { get; set; }
}
}
此例使用双层循环根据省份进行分组。group查询产生的类型是IGrouping<TKey, TElement>类型,实质是列表的列表。
into子句
into子用于group、select、join子句中充当其结果引用的临时标识符。
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
List<Student> students = new List<Student>()
{
new Student() {name="张三", age=22, addr= new List<string>(){ "中国", "山东"}, scores=new List<int>{99, 100} },
new Student() {name="张四", age=23, addr= new List<string>(){ "中国", "山东"}, scores=new List<int>{90, 80}},
new Student() {name="王五", age=21, addr= new List<string>(){ "中国", "北京"}, scores=new List<int>{99, 80}}
};
var query = from student in students
group student by student.scores[1] into student_group
orderby student_group.Key descending
select student_group;
foreach(var group in query)
{
Console.WriteLine(group.Key);
foreach(var s in group)
{
Console.WriteLine(" "+s.name);
}
}
Console.ReadLine();
}
}
public class Student
{
public string name { get; set; }
public int age { get; set; }
public List<string> addr { get; set; }
public List<int> scores { get; set; }
}
}
let 子句
let子句产生一个用于存储查询表达式中的子表达式查询结果的范围变量。
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
List<Student> students = new List<Student>()
{
new Student() {name="张三", age=22, addr= new List<string>(){ "中国", "山东"}, scores=new List<int>{99, 100} },
new Student() {name="张四", age=23, addr= new List<string>(){ "中国", "山东"}, scores=new List<int>{90, 80}},
new Student() {name="王五", age=21, addr= new List<string>(){ "中国", "北京"}, scores=new List<int>{99, 80}}
};
var query = from student in students let c = student.addr
where c[0]=="中国" && c[1]=="山东"
select student;
// 等效where
var query1 = from student in students
where student.addr[0] == "中国" && student.addr[1] == "山东"
select student;
foreach (var s in query)
{
Console.WriteLine(s.name);
}
foreach (var s in query1)
{
Console.WriteLine(s.name);
}
Console.ReadLine();
}
}
public class Student
{
public string name { get; set; }
public int age { get; set; }
public List<string> addr { get; set; }
public List<int> scores { get; set; }
}
}
join子句
join子句可以关联两个数据源,使用equals关键字进行比较两个数据源中的某个属性,而不是用“==”。
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
List<Student> students1 = new List<Student>()
{
new Student() {name="张三", age=22},
new Student() {name="张四", age=23},
new Student() {name="王五", age=21}
};
List<Student> students2 = new List<Student>()
{
new Student() {name="张三", scores=new List<int>{99, 100}},
new Student() {name="张四", scores=new List<int>{90, 80}},
new Student() {name="王五", scores=new List<int>{99, 80}}
};
var query = from student1 in students1
join student2 in students2
on student1.name equals student2.name
select new Student {name=student1.name,
age=student1.age, scores=student2.scores};
foreach (var s in query)
{
Console.WriteLine(string.Format("Name:{0}, Age:{1}, Scores:{2}",
s.name, s.age, s.scores[0]));
}
Console.ReadLine();
}
}
public class Student
{
public string name { get; set; }
public int age { get; set; }
public List<int> scores { get; set; }
}
}
参考
https://learn.microsoft.com/zh-cn/dotnet/csharp/programming-guide/concepts/linq/