C#——Linq详解
Action、Func详解并与lambda表达式结合使用、揭秘linq方法的背后、linq常用的扩展方法
本文章是我听B站杨中科的所做的笔记
杨中科B站视频链接:.NET 6教程,.Net Core 2022视频教程,杨中科主讲_哔哩哔哩_bilibili
委托
1、委托是可以指向方法的类型,调用委托变量时执行的就是变量指向的方法
2、.net 中定义了泛型委托Action(无返回值)和Func(有返回值),所以一般不用自定义委托类型
委托变量不仅可以指向普通方法,还可以指向匿名方法:
Func<int, int, string> f1 = delegate (int i1, int i2) {
return $"{i1}+{i2}={i1 + i2}";
};
string s = f1(1, 2);
lambda表达式
匿名方法可以写成lambda表达式
Func<int, int, string> f1 = (i1,i2) =>{
return $"{i1}+{i2}={i1 + i2}";
};
可以省略参数数据类型,因为编译器根据委托类型推断出参数类型用=>引出来方法体
如果委托没有返回值,且方法体只有一行代码,可省略{}
Action<int, string> a1 = (age, name) => Console.WriteLine($"年龄{age},姓名{name}");
a1(18, "yzk");
如果=>之后的方法体中只有一行代码,且方法有返回值,那么可以省略方法体的{}以及return
Func<int, int, string> f1 = (i1, i2) => $"{i1}+{i2}={i1 + i2}";
如果只有一个参数,参数的()可以省略
Action<string> f1 = s => Console.WriteLine(s);
Func<int, bool> f2 = i => i > 5;
揭秘linq方法的背后
linq中提供了很多集合的扩展方法,配合lambda能简化数据处理
int[] nums = new int[]
{ 3,99,88,77,7,8,9,66,15,7};
IEnumerable<int> items = nums.Where(i=>i>10);//using System.Linq;
可以使用var让编译器的“类型推断”来简化类型的声明,在linq中常用 C#的var和javaScript的var不一样,仍然时强类型的,C#中的弱类型的dynamic
linq常用的扩展方法
linq中提供了大量类似where的扩展方法,简化数据处理。大部分都在System.Linq命令空间中
where方法:每一项数据都会经过predicate的测试,如果针对一个元素,predicate执行的返回值为true,那么这个元素就会放到返回值中。where参数是一个lambda表达式格式的匿名方法,方法的参数e表示当前判断的元素对象。参数的名字不一定非要叫e,不过一般lambda表达式中的变量名长度都不长
1、Count()方法:获取数据条数
int count1 = list.Count(e => e.Salary > 5000 || e.Age < 30);
int count2 = list.Where(e => e.Salary > 5000 || e.Age < 30).Count();
2、Any()方法:是否至少有一条数据
bool b1 = list.Any(e => e.Salary > 8000);
bool b2 = list.Where(e => e.Salary > 8000).Any();
有可能比Count()实现效率高
3、获取一条数据(是否带参数的两种写法)
Single:有且只有一条满足要求的数据,有多条或没有时会报错 SingleOrDefault:最多只有一条满足要求的数据,有多条时会报错,没有时赋默认值 First:至少有一条,返回第一条 选择合适的方法,“防御性编程”
4、排序
order()对数据正序排序 orderByDescending()倒序排序 对于简单类型排序,也许不用lambda表达式。特殊案列:按照最后一个字符排序;用Guid或者随机数进行排序 多规则排序:可以在order()、OrderByDescending()后继续写ThenBy()、ThenByDescending() 案例:优先按照Age排序,如果Age相同再按照Salary排序
list.OrderBy(e => e.Age).ThenByDescending(e => e.Salary)
千万不要写成,会以最后一个进行排序的
list.OrderBy(e => e.Age). OrderByDescending (e => e.Salary)
5、限制结果集,获取部分数据
skip(n)跳过n条数据,Task(n)获取n条数据 案例:获取从第2条开始获取3条数据
var orderedItems1 = list.Skip(2).Take(3);
skip()、Task()也可以单独使用
6、聚合函数
Max()、Min()、Average()、Sum()、Count() Linq中所有的扩展方法几乎都是针对IEnummerable接口的,而集合所有能返回集合的都返回IEnumerable,所以是可以把几乎所有方法“链式使用”的
list.Where(e => e.Age > 30).Min(e=>e.Salary)
7、分组
GroupBy()方法参数是分组条件表达式,返回值为IGrouping<TKey,TSource>类型的泛型IEnumerable,也就是每一组以一个IGrouping对象的形式返回。IGrouping是一个继承自IEnumerable的接口,IGrouping中Key属性表示这一组的分组数据的值。列子:根据年龄分组,获取每组人数、最高工资、平均工资。用var简化编程
8、投影
把集合中的每一项转换为另外一种类型
IEnumerable<int> ages = list.Select(e => e.Age);
IEnumerable<string> names = list.Select(e=>e.Gender?"男":"女");
var dogs = list.Select(p=>new Dog{NickName=e.Name,Age=e.Age});
匿名类型:
var p = new {Name="tom",Id=1};
var p1 = new {name,Id=1,p.Age};
投影与匿名类型:
var items = list.Select(e=>new {e.Name,e.Age,XingBie= e.Gender ? "男" : "女"});
var items = list.GroupBy(e => e.Gender).Select(g=>new { Gender=g.Key,Count=g.Count(),AvgSalary= g.Average(e => e.Salary),MinAge= g.Min(e => e.Age)});
9、链式调用
集合转换:有一些地方需要数组类型或者List类型的变量,我们可以用ToArray()方法和ToList()分别把IEnumerable<T>转换为数组类型和List<T>类型
链式调用:Where、Select、OrderBy、GroupBy、Task、Skip等返回值都是IEnumerable<T>类型,所以可以链式调用。列子:“获取Id>2的数据,然后按照Age分组,并且把分组按照Age排序,然后取出前3条,最后再投影取得年龄、人数、平均工资”
10、Linq另一种倩影
查询语法:使用Where、OrderBy、Select等扩展方法进行数据查询的写法叫做“Linq方法语法”。还有一种“查询语法”的写法
var items2 = from e in list
where e.Salary > 3000
orderby e.Age
select new { e.Name, e.Age, Gender = e.Gender ? "男" : "女" };
区别:运行时没有区别,编译后都是一样的 “查询语法”看起来更酷,但是“方法语法”更实用,因此.net开发者大部分还是用“方法语法”
![Logo](https://devpress.csdnimg.cn/79de2bf0b7994defa4242ef90d5513fa.jpg)
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)