C#Lambda表达式演变和Linq的深度解析
Lambda
一.Lambda的演变
Lambda的演变,从下面的类中可以看出,.Net Framwork1.0时还是用方法实例化委托的,2.0的时候出现了匿名方法,3.0的时候出现了Lambda。
lambda组成是:左边(参数列表)+中间( ()=>符号,表示gose to)+右边(方法体)。无论怎么演变,lambda本质上还是一个方法。
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace _15_linq 8 { 9 /// <summary> 10 /// lambda表达式是什么?? 11 /// 1.lambda说是一个方法也不准确,作用和方法是一样的 12 /// 2.lambda,实际上是一个类中类,里面的一个internal方法,然后绑定到静态的委托类型字段,通过反编译可以看着这些。 13 /// </summary> 14 public class lambadaShow 15 { 16 public delegate void MyDelegate(); 17 public delegate void MyDelegateWhithPara(int x, int y); 18 public void Show() 19 { 20 { 21 //.NTE1.0的做法, 使用委托三部曲:声明,实例化,调用 22 MyDelegate MyDelegateHander = new MyDelegate(Show1); 23 MyDelegateHander.Invoke(); 24 } 25 26 { 27 int i = 100; 28 //.NET 2.0 匿名方法,微软考虑可能要写很多方法,多麻烦啊。这里升级直接把方法搬过来, 29 //去掉方法名,加上delegate关键字就行了。 30 MyDelegate myDelegate = new MyDelegate(delegate () 31 { 32 Console.WriteLine(i);//这里还有一个小知识点,就是匿名方法可以访问外部变量 33 Console.WriteLine("MyDelegate Show"); 34 }); 35 } 36 37 { 38 //.NET 3.0 lambada(作用跟方法一样) 去掉关键字,加上=> gese to 39 //左边参数列表 + gose to+方法体。本质是一个方法 40 //lambada本质:实际上是一个类中类,里面有一个internal方法,然后被绑定到静态的委托字段 41 MyDelegate myDelegate = new MyDelegate(() => 42 { 43 Console.WriteLine("MyDelegate Show"); 44 }); 45 MyDelegateWhithPara myDelegateWhithPara = new MyDelegateWhithPara((int x, int y) => { Console.WriteLine("MyDelegate Show"); }); 46 MyDelegateWhithPara myDelegateWhithPara1 = new MyDelegateWhithPara((x, y) => { Console.WriteLine("MyDelegate Show"); });//可以省略参数类型,编译器自动计算 47 48 MyDelegateWhithPara myDelegateWhithPara2 = (x, y) => { Console.WriteLine("MyDelegate Show"); };//简化版本的实例化委托 49 } 50 } 51 public void Show1() 52 { 53 Console.WriteLine("MyDelegate Show"); 54 } 55 } 56 }
二.从IL层面解读委托
lambda:
实际上是一个类中类,里面的一个internal方法,然后被绑定到静态的委托类型字段
三.Linq
.Net Framework3.0出现了匿名方法,匿名类,lambda,var,扩展方法,这些都是为linq服务的。
1.扩展方法
扩展方法:静态类里面的静态方法,第一个参数类型前面加上this。
扩展方法用途:可以不修改类,或者没办法修改类的情况下,给类添加方法。
1 using System; 2 using System.Runtime.CompilerServices; 3 using System.Threading; 4 using System.Threading.Tasks; 5 6 namespace ConsoleApp1 7 { 8 class Program 9 { 10 static void Main(string[] args) 11 { 12 Student student = new Student 13 { 14 Name = "王小二", 15 Id = 1, 16 Age = 33, 17 }; 18 student.Study(); 19 student.Sing<Student>();//扩展方法 20 bool result = 123.Then(12);//扩展方法 21 Console.ReadKey(); 22 } 23 } 24 public static class Extend 25 { 26 public static void Sing<T>(this T source) where T : Student 27 { 28 Console.WriteLine($"{source.Name}:Sing a Song"); 29 } 30 public static bool Then(this int int1, int int2) 31 { 32 return int1 > int2; 33 } 34 } 35 /// <summary> 36 /// 学生类 37 /// </summary> 38 public class Student 39 { 40 public string Name { get; set; } 41 public int Id { get; set; } 42 public int Age { get; set; } 43 public void Study() 44 { 45 Console.WriteLine("我在学习!"); 46 } 47 } 48 }
2.匿名类
匿名类,在匿名类的语法中,并没有为其命名,而是直接一个new{ }了事的。
var ,object,dynamic这三个是啥?
1>var 是由编译器自动推算的
2>object是一个具体的类型
3>dynamic 主要就是避开编译器的检查
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 //匿名类 6 /*var: 7 * 1>是一个语法糖,由编译器自动推算 8 * 2>var必须在声明的时候就确定类型,类型确定后就不能修改 9 * 3>配合匿名类类型一起使用*/ 10 var student = new 11 { 12 Id=1, 13 Name="匿名类", 14 Age=35, 15 }; 16 Console.WriteLine($"匿名类:{student.Id},{student.Name},{student.Age}"); 17 18 //object是一种具体类型,不存在Id或者其他属性的 19 object ostudent = new 20 { 21 Id = 2, 22 Name = "object类型", 23 Age = 36, 24 }; 25 //Console.WriteLine(ostudent.Id); //object是一种类型,不存在Id或者其他属性的 26 27 //dynamic就是避开编译器的检查 28 dynamic dStudent = new 29 { 30 Id = 1, 31 Name = "dynamic类型", 32 Age = 35, 33 }; 34 Console.WriteLine($"dynamic类型:{dStudent.Id},{dStudent.Name},{dStudent.Age}"); 35 Console.ReadKey(); 36 } 37 }
下面开始进入正题,说说linq,以及一些常用的:
1>过滤小能手:Where方法
Where完成对数据集合的过滤,需要提供一个带bool返回值的“筛选器”(匿名方法,委托,lambda表达式都可以),从而表明数据集合中某个元素是否被返回。
2>投影小行家Select方法
Select是完成对数据的转换,返回新的对象集合。
3>排序小牛OrderBy
OrderBy是完成对数据的排序
4>连接小助手Join
Join连接两个类之间的关联联系
5>分组教授GroupBy
GroupBy对数据集合进行分类
下面代码对于上面进行了验证,运行结果如下
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 namespace ConsoleApp1 5 { 6 class Program 7 { 8 public delegate bool MyDelegate(Student student); 9 static void Main(string[] args) 10 { 11 LinqShow linkShow = new LinqShow(); 12 linkShow.Show(); 13 Console.ReadKey(); 14 } 15 } 16 public class LinqShow 17 { 18 #region 先准备一堆学生 19 static List<Student> GetStudentList() 20 { 21 List<Student> listStudent = new List<Student>() 22 { 23 new Student(){Id=4,Gender= true, Name="小四", Age=33,}, 24 new Student(){Id=1,Gender= false, Name="王小一", Age=30,}, 25 new Student(){Id=2,Gender= true, Name="王小二", Age=31,}, 26 new Student(){Id=3,Gender= false, Name="王小三", Age=32,}, 27 }; 28 return listStudent; 29 } 30 static List<Class> GetClassList() 31 { 32 List<Class> listClass = new List<Class>() 33 { 34 new Class() 35 { 36 ClassId=1, 37 ClassName="初级班", 38 }, 39 new Class() 40 { 41 ClassId=2, 42 ClassName="高级班", 43 }, 44 new Class() 45 { 46 ClassId=3, 47 ClassName="架构班", 48 }, 49 new Class() 50 { 51 ClassId=4, 52 ClassName="微信班", 53 }, 54 }; 55 return listClass; 56 } 57 #endregion 58 59 /// <summary> 60 /// Linq To Object(Enumerable) 61 /// Where:完成对数据集合的过滤,通过委托封装完成通用代码,泛型+迭代器去提供特性 62 /// </summary> 63 public void Show() 64 { 65 #region linq to object Show 66 List<Student> listStudent = GetStudentList(); 67 List<Class> listClass = GetClassList(); 68 Console.WriteLine("*****************where 1***********************"); 69 {//where 完成对数据集合的筛选 70 var list1 = from s in listStudent 71 where s.Age > 30 && s.Gender == true 72 select s; 73 foreach (var item in list1) 74 { 75 Console.WriteLine(item.Age); 76 } 77 78 } 79 {//where 完成对数据集合的筛选 80 Console.WriteLine("****************Where 2************************"); 81 var list = listStudent.Where<Student>(s => s.Age > 30 && s.Gender == true); 82 foreach (var item in list) 83 { 84 Console.WriteLine(item.Age); 85 } 86 } 87 {//Select 完成对数据的转换 88 Console.WriteLine("****************Select 1************************"); 89 var list = from s in listStudent 90 where s.Age > 30 91 select new 92 { 93 IdName = s.Id + s.Name, 94 AgeName = s.Age + s.Name, 95 }; 96 foreach (var item in list) 97 { 98 Console.WriteLine($"{item.IdName},{item.AgeName}"); 99 } 100 } 101 102 {//Select 完成对数据的转换 103 Console.WriteLine("****************Select 2************************"); 104 var list2 = listStudent.Where<Student>(s => s.Age > 30).Select(s => new 105 { 106 IdName = s.Id + s.Name, 107 AgePerson = s.Age == 33 ? "大龄了" : "也不小了", 108 }); 109 foreach (var item in list2) 110 { 111 Console.WriteLine(item.IdName + item.AgePerson); 112 } 113 //或者 114 var list2_1 = listStudent.Where<Student>(s => s.Age > 30) 115 .Select(s => new 116 { 117 Name = s.Name, 118 Age = s.Age, 119 Length = s.Name.Length 120 }); 121 foreach (var item in list2_1) 122 { 123 Console.WriteLine($"{item.Name},{item.Age},{item.Length}"); 124 } 125 } 126 {//OrderBy完成对数据集合的排序,按照Id排序之前Id=4的“小四”是在第一个位置的,排序后“小四”在最后了 127 Console.WriteLine("*******************OrderBy*********************"); 128 var list3 = listStudent.Where<Student>(s => s.Age > 10) 129 .OrderBy(s => s.Id); 130 foreach (var item in list3) 131 { 132 Console.WriteLine(item.Name); 133 } 134 } 135 { //Skip 跳过几条,从输出结果可见,“小四”这条信息被跳过去了 136 Console.WriteLine("*******************Skip*********************"); 137 var list3 = listStudent.Where<Student>(s => s.Age > 10) 138 .Select(s => new 139 { 140 IdOrder = s.Id, 141 NameId = s.Name + s.Id, 142 AgeId = s.Age + s.Id, 143 }) 144 .OrderBy(s => s.IdOrder) 145 .Skip(1); 146 foreach (var item in list3) 147 { 148 Console.WriteLine(item.NameId); 149 } 150 } 151 { 152 //Take 获取几条,从输出结果可见,获取了前面两条信息:"小四","王小一" 153 Console.WriteLine("*******************Take*********************"); 154 var list3 = listStudent.Where<Student>(s => s.Age > 10) 155 .Take(2); 156 foreach (var item in list3) 157 { 158 Console.WriteLine(item.Name); 159 } 160 } 161 {//group by 162 Console.WriteLine("*****************GroupBy********************"); 163 var list4 = from s in listStudent 164 where s.Age > 30 165 group s by s.Id into sg 166 select new 167 { 168 key = sg.Key, 169 maxAge = sg.Max(t => t.Age) 170 }; 171 foreach (var item in list4) 172 { 173 Console.WriteLine($"key={item.key},maxAge={item.maxAge}"); 174 } 175 } 176 {//GroupBy 177 Console.WriteLine("*******************GroupBy******************"); 178 var list5 = listStudent.GroupBy(s => s.Gender == true); 179 foreach (var group in list5) 180 { 181 Console.WriteLine(string.Format("group:{0}", group.Key == true ? "男" : "女")); 182 foreach (var p in group) 183 { 184 Console.WriteLine(p.Name); 185 } 186 } 187 } 188 {//join 189 { 190 Console.WriteLine("******************join********************"); 191 var list6 = from s in listStudent 192 join c in listClass on s.Id equals c.ClassId 193 select new 194 { 195 Name = s.Name, 196 ClassName = c.ClassName 197 }; 198 foreach (var item in list6) 199 { 200 Console.WriteLine($"Name={item.Name},ClassName={item.ClassName}"); 201 } 202 203 Console.WriteLine("******************join********************"); 204 var list7 = listStudent.Join(listClass, s => s.Id, c => c.ClassId, (s, c) => new 205 { 206 Name = s.Name, 207 ClassName = c.ClassName 208 }); 209 foreach (var item in list7) 210 { 211 Console.WriteLine($"{item.Name},{item.ClassName}"); 212 } 213 } 214 } 215 #endregion 216 } 217 } 218 219 /// <summary> 220 /// 学生类 221 /// </summary> 222 public class Student 223 { 224 public string Name { get; set; } 225 public int Id { get; set; } 226 public int Age { get; set; } 227 public bool Gender { get; set; } 228 public override string ToString() 229 { 230 return string.Format("{0}-{1}-{2}-{3}", Id, Name, Age, Gender == true ? "男" : "女"); 231 } 232 public void Study() 233 { 234 Console.WriteLine("我在学习!"); 235 } 236 } 237 /// <summary> 238 /// 班级实体 239 /// </summary> 240 public class Class 241 { 242 public int ClassId { get; set; } 243 public string ClassName { get; set; } 244 } 245 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?