C#Lambda表达式演变和Linq的深度解析
阅读原文时间:2023年07月08日阅读:1

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 ///

10 /// lambda表达式是什么?? 11 /// 1.lambda说是一个方法也不准确,作用和方法是一样的 12 /// 2.lambda,实际上是一个类中类,里面的一个internal方法,然后绑定到静态的委托类型字段,通过反编译可以看着这些。 13 ///
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();//扩展方法
20 bool result = 123.Then(12);//扩展方法
21 Console.ReadKey();
22 }
23 }
24 public static class Extend
25 {
26 public static void Sing(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 ///

36 /// 学生类 37 ///
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 GetStudentList()
20 {
21 List listStudent = new List()
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 GetClassList()
31 {
32 List listClass = new List()
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 ///

60 /// Linq To Object(Enumerable) 61 /// Where:完成对数据集合的过滤,通过委托封装完成通用代码,泛型+迭代器去提供特性 62 ///
63 public void Show()
64 {
65 #region linq to object Show
66 List listStudent = GetStudentList();
67 List 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(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(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(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(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(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(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 /// 220 /// 学生类 221 ///
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 /// 238 /// 班级实体 239 ///
240 public class Class
241 {
242 public int ClassId { get; set; }
243 public string ClassName { get; set; }
244 }
245 }