前面的话
这篇文章主要是在工具书中linq的基础上,我做了一些归纳。
目录
- 什么是Linq
- 方法语法和查询语法
- 查询表达式的结构
- 标准查询运算符
什么是Linq?
- Linq(link)代表语言集成查询(Language Integrated Query)
- Linq是.NET框架的扩展,它允许我们以使用SQL查询数据库的方式来查询数据集合。
- 使用Linq,你可以从数据库、程序对象的集合以及XML文档中查询数据。
一个例子
static void Main()
{
int[] numbers = {2,12,5,15};//数据源
IEnumerable<int> lowNums =
from n in numbers
where n < 10
select n;
foreach(var x in lowNums) //执行查询
Console.Write("{0},",x);
}
方法语法和查询语法
我们在写Linq查询时可以使用两种形式的语法:查询语法和方法语法。
- 方法语法使用标准的方法调用。这些方法是一组叫做查询运算符的方法。例:numbers.Where ( x => x < 20);
- 查询语法看上去和SQL语句很相似,使用查询表达式书写。
例: from n in numbers
where n < 10
select n;
查询表达式的结构
- 子句必须按照一定的顺序出现
- from 子句和 select … group子句这两部分是必需的。
- 其他子句是可选的。
- 在Linq查询表达式中,select子句在表达式最后。
可以有任意多的from… let… where子句
from子句、join子句、class Program { public class Student { // 声明类 public int StID; public string LastName; } public class CourseStudent { public string CourseName; public int StID; } //初始化数组 static Student[] students = new Student[] { new Student { StID =1,LastName ="Carson"}, new Student{ StID= 2,LastName="Klassen"}, new Student{ StID =3,LastName = "Fleming"} }; static CourseStudent[] studentsInCourses = new CourseStudent[] { new CourseStudent { CourseName = "Art", StID =1}, new CourseStudent {CourseName ="Art",StID=2}, new CourseStudent {CourseName ="History",StID=1}, new CourseStudent {CourseName ="History",StID=3}, new CourseStudent {CourseName ="Physics",StID=3} }; static void Main() { //查找所有选择了历史课的学生的姓氏 var query = from s in students join c in studentsInCourses on s.StID equals c.StID where c.CourseName == "History" select s.LastName; foreach(var q in query) Console.WriteLine("Student taking History:{0},"q); } }
from… let… where
static void Main()
{
var groupA = new[]{3,4,5,6};
var groupB = new[]{6,7,8,9};
var someInts = from a in groupA
from b in groupB
let sum = a+b
where sum == 12
select new {a,b,sum};
foreach(var a in someInts)
Console.WriteLine(a);
}
static void Main()
{
var groupA = new[]{3,4,5,6};
var groupB = new[]{6,7,8,9};
var someInts = from int a in groupA
from int b in groupB
let sum = a+b
where sum>=11
where a==4
select new{a , b ,sum};
foreach(var a in someInts)
Console.WriteLine(a);
}
orderby子句
static void Main(){
var students = new []
{
new {LName ="Jones",FName="Mary",Age =19,Major ="History"},
new {LName="Fleming",FName="Carol",Age=20,Major="CompSci"},
new{LName ="Fleming",FName = "Carol",Age =21,Major ="History"}
};
var query = from student in students
orderby student.Age
select student;
foreach(var s in query)
{
Console.WriteLine("{0},{1}:{2}-{3}",s.LName,s.FName,s.Age,s.Major);
}
}
标准查询运算符
标准查询运算符由一系列API方法组成,它能让我们查询任何.NET数组或集合。有关标准查询运算符的重要特性:
class Program
{
static int[] numbers = new int[]{2,4,6};
static void Main()
{
int total = numbers.Sum();
int howMany= numbers.Count();
Console.WriteLine("Total:{0},Count:{1}",total,howMany);
}
}
共有47个标准查询运算符,可用来操作一个或多个序列。序列是指实现了Ienumerable<>接口的类,包括List<>、Dictionary<>、Stack<>、Array等。标准查询运算符可以帮助我们以非常强大的方式才查询和操作这些类型的对象。
查询表达式和标准查询运算符
查询表达式和方法语法这两种表达式也可以组合。
static void Main()
{
var numbers = new int[]{2,6,4,8,10};
int howMany= (from n in numbers
where n <7
select n).Count();
Console.WriteLine("Count:{0}",howMany);
}
标准查询运算符
运算符名 | 描述 |
---|---|
Where | 根据给定的谓词对序列进行过滤 |
Select | 指定要包含一个对象或对象的一部分 |
SelectMany | 一种查询类型,返回集合的集合。该方法将这些结果合并为一个单独的集合 |
Take | 接受一个输入参数count,返回序列中前count个对象 |
Skip | 接受一个输入参数count,返回序列中的前count个对象 |
TakeWhile | 接受一个谓词,开始迭代该序列,只要谓词对当前项的计算结果为true,就选择该项。在谓词返回第一个false的时候,该项和其余项都被丢弃 |
SkipWhile | 接受一个谓词,开始迭代该序列,只要谓词对当前项的计算结果为true,就跳过该项。在谓词返回第一个false的时候,该项和其余项都会被选择 |
Join | 对两个序列执行内联结,第一个序列中的各个元素都与第二个序列中的元素集合相关联 |
GroupJoin | 可以产生层次结果的联结,第一个序列中的各个元素都与第二个序列中的元素集合相关联 |
Concat | 连接两个序列 |
OrderBy/ThenBy | 根据一个或多个键对序列中的元素排序 |
Reverse | 反转序列中的元素 |
GroupBy | 分组序列中的元素 |
Distinct | 去除序列中的重复项 |
Union | 返回两个序列的并集 |
Intersect | 返回两个序列的交集 |
Except | 操作两个序列。返回的是第一个序列中不重复的元素减去同样位于第二个序列中的元素 |
AsEnumerable | 将序列作为IEnumerable返回 |
ToArray | 将序列作为数组返回 |
ToList | 将序列作为List返回 |
ToDictionary | 将序列作为Dictionary |
ToLookup | 将序列作为LookUp |
OfType | 所返回的序列中的元素是指定的类型 |
Cast | 将序列中所有的元素强制转换为给定的类型 |
SequenceEqual | 返回一个布尔值,指定两个序列是否相等 |
First | 返回序列中的第一个与谓词匹配的元素。如果没有元素与谓词匹配,就抛出InvalidOperation-Exception |
FirstOrDefault | 返回序列中的第一个与谓词匹配的元素。如果没有给出为,方法放回序列的第一个元素。如果没有元素与谓词匹配,就使用该类型的默认值 |
Last | 返回序列中的最后一个与谓词匹配的元素。如果没有元素与谓词匹配,就抛出InvalidOperation-Exception |
LastOrDefault | 返回序列中最后一个与谓词匹配的元素。如果没有元素与谓词匹配,就返回默认值 |
Single | 返回序列中与谓词匹配的单个元素。如果没有元素匹配,或多于一个元素匹配,就抛出异常 |
SingleOrDefault | 返回序列中与谓词匹配的单个元素。如果没有元素匹配,或多于一个元素匹配,就返回默认值 |
ElementAt | 给定一个参数n,返回序列中的第n+1个元素 |
ElementAtOrDefault | 给定一个参数n,返回序列中的第n+1个元素。如果索引超出范围,就返回默认值 |
DefaultIfEmpty | 提供一个在序列为空(empty)时的默认值 |
Range | 给定一个start整型和count整型,该方法返回的序列包含count个整型,其中第一个元素的值为start,之后每个后续元素都比前一个大1 |
Repeat | 给定一个T类型的element和一个count整数,该方法返回的序列具有count个element副本 |
Empty | 返回给定类型T的空序列 |
Any | 返回一个布尔值,指明序列中是否存在满足谓词的元素 |
All | 返回一个布尔值,指明序列中的全部元素是否都满足谓词 |
Contains | 返回一个布尔值,指明序列中是否包含给定的元素 |
Count | 返回序列中元素的个数(int)。它的重载可以接受一个谓词,返回满足谓词的个数 |
LongCount | 返回序列中元素的个数(long)。他的重载可以接受一个谓词,返回满足谓词的元素个数 |
Sum | 返回序列中的值的总和 |
Min | 返回序列中最小的值 |
Max | 返回序列中最大的值 |
Average | 返回序列中的平均值 |
Aggregate | 连续对序列中的各个元素应用给定的函数 |
方法语法中使用委托
class Program
{
static bool IsOdd(int x) //委托对象使用的方法
{
return x%2==1; //如果x是奇数,返回true
}
static void Main()
{
int[] intArray = new int[]{3,4,5,6,7,9};
Func<int,bool>myDel = new Func<int,bool>(IsOdd);//委托对象
var countOdd = intArray.Count(myDel);
Console.WriteLine("Count of odd numbers:{0}",countOdd);
}
}
自己的实践
class Program
{
static bool IsOdd(string x)
{
return x.Length>4 ;
}
static void Main(string[] args)
{
string[] names = { "Tom", "Dick", "Harry", "Mary", "Jay","Jay"};
string[] fimally = { "Mary", "Jay","Jay", "Tom", "Dick", "Harry"};
// 编译器将会从Lambda表达式 n => n.Length推断出TResult为int类型
Func<string, bool> myDel = new Func<string, bool>(IsOdd);//委托对象
List<pet> pets = new List<pet>() { new pet(){Age = 1, Sex = "公"}, new pet(){Age = 2, Sex = "母"} };
List<pet> pett= pets.Where<pet>(n => n.Age == 1).ToList();
foreach (pet p in pett)
{
Console.WriteLine("年龄是:" + p.Age + ";性别是:" + p.Sex);
}
}
}
class pet
{
public int Age;
public string Sex;
}