LINQ
1、泛型参数命名规范
TSource,输入参数类型
TResult,输出参数类型
TKey,用于排序、分组、或者
2、OfType() 比如在Array集合中筛选出指定类型的数据;比如从一堆父类中查找出指定的子类,用得比较多
OfType()方法也用于筛选。 与其他运算符不同的是,OfType()定义在IEnumerable上,而不是IEnumerable<T>,它的作用是从非泛型集合中筛选出某一类型的成员并返回
IEnumerable<T>。
3、Cast() 比如Array集合,我们把里面的数据全部转换为int类型,但是转换不成功会抛出异常
4、调用Orderby还想继续排序就ThenBy()
5、Select()投影,可以直接投影new一个对象,但可以有个索引在里面进行操作
var query = col.Select((x, index) => new { Title = x.Name, Index = index}),
比如MVC网站的下拉列表填充数据:
IEnumerable<SelectListItem> list =
col.Select(x => new SelectListItem { Text = x.Name, Value = x.Code });
6.Take()和Skip() 取和跳过,sql中的top可以为take,用于分页
7、TakeWhile()和SkipWhile() 如果是进行过排序的集合就有用了
取当条件不满足时继续,跳过不满足的。
int[] array = { 1, 2, 10, 4, 5};
var query = array.TakeWhile(x => x <= 5); // 输出1,2
var query = array.SkipWhile(x => x <= 5); // 输出10,4,5
8、Reverse() 反转序列
9、DefaultIfEmpty() 当序列为空时,DefaultIfEmpty()为序列添加一个元素,使用元素的默认值,或者指定元素的值,例如:
int[] array = { };
var query = array.DefaultIfEmpty(); // 输出0
var query2 = array.DefaultIfEmpty(100); // 输出100
注意:因为int是值类型,默认值是0.当为类类型的时候,默认值为null,如果不指定一个值就会抛出未将对象引用到实例
10.Distinct() 去重
值类型:判断序列元素是否重复,需要元素实现IComparable<T>接口,值类型实现了这个接口。
自定义类型:我们可以调用Distinct()的重载方法,传递一个IEqualityComparer<T>类型,它包含了对象比较的算法 ,因此,再建一个类PointComparer,让它去实现IEqualityComparer<T>接口:
public class PointComparer : IEqualityComparer<Point> {
public bool Equals(Point a, Point b) {
return a.X == b.X;
}p
ublic int GetHashCode(Point obj) {
return obj.X;
}
}
然后调用Distinct的重载方法,此时可以得到预期的结果:
PointComparer cmp = new PointComparer();
var query = array.Distinct(cmp); // 得到1,2
11.GroupBy()
在T-SQL中,Group By只能和聚合函数一起搭配使用,返回的结果仍然是一个表(Flat)。 但是在LINQ中,GroupBy()的结果可以是一个树形结构,即序列中的元素也是一
个序列。
group by 之后会产生一个key,key就是我们的分组ID’(item.key),之后再次循环item里面的值才是我们想要的对象:
var query = col.GroupBy(x => x.Category);
foreach (var item in query) {//循环每个组
Console.WriteLine("<{0}>", item.Key);
foreach (var p in item) {//循序每个组的全部子集
Console.WriteLine(p.ToString());
}
}
GroupBy()还包含一个重载方法,使用投影操作将TSource映射为其他类型 :
var query = col.GroupBy(x => x.Category,
x => new SelectListItem { Text = x.Code + x.Name,
Value = x.Price.ToString() });
获取数据的操作跟我们之前的一样 。SelectListItem 可以是任意类型,比如匿名
12.Intersect()和Except()
Intersect()返回两个序列中相同元素构成的序列。对于自定义类型来说跟PointComparer 类一样:
int[] array1 = { 0, 1, 2 };
int[] array2 = { 2, 3, 4 };
var query = array1.Intersect(array2); // 得到 2
Except()与Intersect()相反,返回第一个序列中有而第二个序列中没有的元素:
var query = array1.Except(array2); // 得到 0,1
13.Concat()和Union()
Concat()运算符用于连接两个序列。
Union()运算符也用于连接两个序列,但是会剔除相同的项目
var query = array1.Concat(array2); // 得到 0,1,2,2,3,4
var query = array1.Union(array2); // 得到 0,1,2,3,4
5.4.2 返回其他序列类型
ToArray()、 ToList()、 ToDictionary()、 ToLookUp()四个方法用于将IEnumerable<T>转换为相应的类型。 在转换时,会执行遍历,因此这几个方法都是立即执行的,没有进行延时加载。
5.4.3 返回序列中元素
1.ElementAt()和ElementAtOrDefault()
ElementAt()以序列中元素的位置作为参数,返回该元素。 如果元素不存在,则抛出异常。
ElementAtOrDefault()在元素不存在时返回该类型的默认值。 对于引用类型来说,其默
认值为null。 int类型为0,因为是返回默认值,所以不会抛出异常
2.First()和FirstOrDefault()
First()和Where()类似,只不过First()返回满足条件的第一个序列元素,而Where()返回
所有满足条件的序列元素。 当元素不存在时,First()会抛出异常,而FirstOrDefault()返回元素的默认值(没有返回null)
int[] array = { 1, 2, 3, 4 };
int item = array.First(x => x %2 == 0); // 得到 2
int item2 = array.First( x => x==10); // 异常:序列不包含任何匹配元素
int item3 = array.FirstOrDefault(x=>x==10); // 得到 0
当不传递参数时,First()返回序列中的首个元素:
int item = array.First(); // 得到1
3.Last()和LastOrDefault() 跟上面的相反
4.Single()和SingleOrDefault()
Single()与First()类似,只不过Single()要求序列中有且只有一个满足条件的项,如果满足条件的有两项,则会抛出异常。 SingleOrDefault()要求有一个或零个满足条件的项,当满
足条件的项为零个时,返回默认值:
int[] array = { 1, 2, 2, 3 };
int item2 = array.Single(x => x == 2); // 异常:序列中包含一个以上的元素
int item3 = array.SingleOrDefault(x => x == 10); // 得到0
Single()还有一个不包含任何查询条件的重载,当序列中有且仅有一个元素时,返回该元素,否则抛出异常:
int[] array = { 1 };
int item = array.Single(); // 得到 1
int[] array2 = { 1, 2 };
int item2 = array2.Single(); // 抛出异常:序列中包含一个以上的元素
5.4.4 返回标量值
1.Count()和LongCount()
这两个方法用于返回序列中的元素数目,不同的是Count()返回int类型,而LongCount()返回long类型。
2.Max()、 Min()、 Average()和Sum()
从名称就可以看出这几个方法的用意,Max()返回序列中最大的项,Min()返回序列中最
小的项,Average()返回序列中各项的平均值,Sum()返回序列中各项的总和:
3.Aggregate()
Aggregate()运算符用于返回自定义的聚合,例如,可以将序列中每个元素乘以2,再将
它们相加起来:
int[] array = { 2, 3, 5 };
int sum = array.Aggregate(0, (total, x) => total + (x * 2));
Console.WriteLine(sum)
上面的0是total的初始值,total是运算后的结果,Lambda表达式为运算的方法,上面
的代码相当于:
int[] array = { 2, 3, 5 };
int total = 0;
foreach (int x in array) {
total = total + (x * 2);
}i
nt sum = total;
Console.WriteLine(sum);
4.Contains()、 Any()、 All()和SequenceEqual()
这4个方法都返回bool类型,用作条件判断 :
Contains()判断某一个元素是否存在于序列中
Any()判断序列中是否存在满足表达式的元素,只要有一个元素满足,则返回True。 当
调用无参数的重载方法时,Any()用于判断序列中是否包含元素。
All()判断序列中所有的元素是否都满足表达式,只要有一个元素不满足,则返回False。
SequenceEqual(),用于逐项比较两个序列,当两个序列中的元素数目相同,并且序列
中相同位置的元素也相同时,返回True,否则返回False:
int[] array = { 0, 1, 2 };
int[] array2 = { 0, 1, 2, 3 };
int[] array3 = { 0, 1, 2 };
var query = array.SequenceEqual(array2); // False
var query2 = array.SequenceEqual(array3); // True
5.4.5 其他方法
还有一些方法,它们也定义在System.Linq.Enumerable类中,却不是扩展方法,只是普通的静态方法,因此,只能在Enumerable类上调用。
Empty()用于创建一个空的序列,由泛型参数指定序列的元素类型:
IEnumerable<string> list1 = Enumerable.Empty<string>(); //创建一个空的string序列
IEnumerable<int> list2 = Enumerable.Empty<int>(); //创建一个空的int序列
Console.WriteLine(list1.Count()); // 0
list1的实际类型可以通过调用GetType().FullName来获得:
Console.WriteLine(list1.GetType().FullName); // System.String[]
Range()方法只能用于int类型,用于生成由连续数字构成的序列,序列中的元素依次加
1:
IEnumerable<int> seq = Enumerable.Range(0, 3); // 0,1,2,常跟select用于代替循环的操作
Repeat()方法与Range()类似,只不过用于生成重复的数字:
IEnumerable<int> seq = Enumerable.Repeat(0, 3); // 0,0,0