lambda,linq
一:什么是Lambda表达式
lambda表达式是实例化委托的一个参数,就是一个方法,具体实现如下:
1 { 2 //.NetFramework 1.0-1.1的时候这样应用 3 NoReturnNoPara method = new NoReturnNoPara(DoNothing); 4 method.Invoke(); 5 6 7 //.NetFramwork2.0 匿名方法出现,delegate关键字,可以访问局部变量 8 int i = 0; 9 NoReturnWithPara method1 = new NoReturnWithPara(delegate (int id, int age) 10 { 11 Console.WriteLine(i); 12 Console.WriteLine($"{id} 今年{age}岁了!"); 13 }); 14 method1.Invoke(1, 30); 15 16 17 //.NetFramwork3.0 把delegate关键字去掉,然后增加了一个箭头goes to 18 //lambda表达式:参数列表=>方法体 19 NoReturnWithPara method2 = new NoReturnWithPara((int id, int age) => 20 { 21 Console.WriteLine(i); 22 Console.WriteLine($"{id} 今年{age}岁了!"); 23 }); 24 method2.Invoke(1, 30); 25 26 NoReturnWithPara method3 = new NoReturnWithPara((id, age) => 27 { //省略参数类型,但是编译器可以根据委托推断出类型,是语法糖 28 Console.WriteLine(i); 29 Console.WriteLine($"{id} 今年{age}岁了!"); 30 }); 31 method3.Invoke(1, 30); 32 33 //如果方法体只有一行,可以去掉大括号和分号 34 NoReturnWithPara method4 = new NoReturnWithPara((id, age) => Console.WriteLine($"{id} 今年{age}岁了!")); 35 method4.Invoke(1, 30); 36 37 //如果方法体只有一行,可以去掉大括号和分号,还可以去掉new NoReturnWithPara,这个也是编译器语法糖 38 NoReturnWithPara method5 = (id, age) => Console.WriteLine($"{id} 今年{age}岁了!"); 39 method4.Invoke(1, 30); 40 41 //下面带有返回值的 42 Func<int> func0 = () => { return DateTime.Now.Month; };//有一个返回值 43 Func<int> func1 = () => DateTime.Now.Month; //如果方法体只有一行,去掉大括号分号和return 44 45 }
使用反编译工具看会产生一个私有sealed类,然后会看到lambda表达式都会生成一个方法名字,然后都会在包括在Sealed类里面
二:匿名类(.netFramwork3.0)
匿名类是.netFramwork3.0出现的,语法是:object object=new{};
下面有几种声明方式:
1 object model = new//3.0 2 { 3 Id = 2, 4 Name = "undefined", 5 Age = 25, 6 ClassId = 2 7 }; 8 // Console.WriteLine(model.Id);//object 编译器不允许 9 10 var varModel = new//3.0 编译后是有一个真实的类 11 { 12 Id = 2, 13 Name = "undefined", 14 Age = 25, 15 ClassId = 2 16 }; 17 Console.WriteLine(varModel.Id); //编译器可以找到 18 //varModel.Id = 123;//只能get 没有set 19 //反射可以找到 20 21 22 //dynamic避开编译器 23 dynamic dModel = new//4.0 24 { 25 Id = 2, 26 Name = "undefined", 27 Age = 25, 28 ClassId = 2 29 }; 30 31 var s = dModel;
下面说一下var这个类型
var:是一个语法糖,由编译器自动推算出变量的类型,一般配合匿名类型使用,然后如遇到复杂类型,可以用之代替,但使用时,以下几点需要注意:
1:var声明的时候一定要确定类型,比如var dd=null或者var aa; 都是编译不通过的
2:一旦确定类型后是不能修改类型的,比如: var s = "加菲猫";则后面不能修改为:s=122;
三:扩展方法(.netFramwork3.0)
什么是扩展方法?答案则是静态类里面的静态方法,第一个参数类型前面加上this
具体如下:
1 public static class ExtendMethod 2 { 3 public static void Show<T>(this T t)//最好加约束 4 { } 5 6 public static void Sing(this Student student) 7 { 8 Console.WriteLine($"{student.Name} Sing a Song"); 9 } 10 11 /// <summary> 12 /// null默认是defaultValue,默认是0 13 /// </summary> 14 /// <param name="iValue"></param> 15 /// <param name="defaultValue"></param> 16 /// <returns></returns> 17 public static int ToInt(this int? iValue, int defaultValue = 0) 18 { 19 return iValue ?? defaultValue; 20 } 21 22 public static bool Than(this int value1, int value2) 23 { 24 return value1 > value2; 25 } 26 27 28 /// <summary> 29 /// 扩展基类型,导致任何子类都有这个方法,而且还可能被覆盖啥的 30 /// </summary> 31 /// <param name="iValue"></param> 32 /// <returns></returns> 33 public static int Length(this object oValue) 34 { 35 return oValue == null ? 0 : oValue.ToString().Length; 36 } 37 38 }
然后调用的时候如下:
int? iValue1 = nul int? iValue = 2; iValue1.ToInt(); iValue1.Length(); s.Length(); 123.Than(234);
扩展方法的用途:
1:适合用于一些不经常修改的地方
2:适合组件式开发的扩展(.netcore),定义接口或者类,是按照最小需求,但是开发的时候又经常需要一些方法,就是通过扩展方法,context.Response.WriteAsync
还有中间件的注册
3:扩展一些常见操作
扩展方法缺陷:优先调用类型的实例方法(有隐患),会污染基础类型,一般少为object 或者没有约束的泛型去扩展,扩展基类型,导致任何子类都有这个方法,而且还可能被覆盖啥的
三:linq
linq和lamda的关系:
lambda和linq的关系
lambda:是实例化委托的快捷方式,是一个方法
linq:是基于委托(lambda)的封装,代码重用,逻辑解耦,是一个帮助类库
linq是用泛型,委托,lamda实现的,总的来说:把对数据操作的通用部分完成,把可变的交给委托,使用者只关心可变部分。
我们还是以例子来讲,先初始化一些基础数据
1 private List<Student> GetStudentList() 2 { 3 #region 初始化数据 4 List<Student> studentList = new List<Student>() 5 { 6 new Student() 7 { 8 Id=1, 9 Name="赵亮", 10 ClassId=2, 11 Age=35 12 }, 13 new Student() 14 { 15 Id=1, 16 Name="再努力一点", 17 ClassId=2, 18 Age=23 19 }, 20 new Student() 21 { 22 Id=1, 23 Name="王炸", 24 ClassId=2, 25 Age=27 26 }, 27 new Student() 28 { 29 Id=1, 30 Name="疯子科学家", 31 ClassId=2, 32 Age=26 33 }, 34 new Student() 35 { 36 Id=1, 37 Name="灭", 38 ClassId=2, 39 Age=25 40 }, 41 new Student() 42 { 43 Id=1, 44 Name="黑骑士", 45 ClassId=2, 46 Age=24 47 }, 48 new Student() 49 { 50 Id=1, 51 Name="故乡的风", 52 ClassId=2, 53 Age=21 54 }, 55 new Student() 56 { 57 Id=1, 58 Name="晴天", 59 ClassId=2, 60 Age=22 61 }, 62 new Student() 63 { 64 Id=1, 65 Name="旭光", 66 ClassId=2, 67 Age=34 68 }, 69 new Student() 70 { 71 Id=1, 72 Name="oldkwok", 73 ClassId=2, 74 Age=30 75 }, 76 new Student() 77 { 78 Id=1, 79 Name="乐儿", 80 ClassId=2, 81 Age=30 82 }, 83 new Student() 84 { 85 Id=1, 86 Name="暴风轻语", 87 ClassId=2, 88 Age=30 89 }, 90 new Student() 91 { 92 Id=1, 93 Name="一个人的孤单", 94 ClassId=2, 95 Age=28 96 }, 97 new Student() 98 { 99 Id=1, 100 Name="小张", 101 ClassId=2, 102 Age=30 103 }, 104 new Student() 105 { 106 Id=3, 107 Name="阿亮", 108 ClassId=3, 109 Age=30 110 }, 111 new Student() 112 { 113 Id=4, 114 Name="37度", 115 ClassId=4, 116 Age=30 117 } 118 , 119 new Student() 120 { 121 Id=4, 122 Name="关耳", 123 ClassId=4, 124 Age=30 125 } 126 , 127 new Student() 128 { 129 Id=4, 130 Name="耳机侠", 131 ClassId=4, 132 Age=30 133 }, 134 new Student() 135 { 136 Id=4, 137 Name="Wheat", 138 ClassId=4, 139 Age=30 140 }, 141 new Student() 142 { 143 Id=4, 144 Name="Heaven", 145 ClassId=4, 146 Age=22 147 }, 148 new Student() 149 { 150 Id=4, 151 Name="等待你的微笑", 152 ClassId=4, 153 Age=23 154 }, 155 new Student() 156 { 157 Id=4, 158 Name="畅", 159 ClassId=4, 160 Age=25 161 }, 162 new Student() 163 { 164 Id=4, 165 Name="混无痕", 166 ClassId=4, 167 Age=26 168 }, 169 new Student() 170 { 171 Id=4, 172 Name="37度", 173 ClassId=4, 174 Age=28 175 }, 176 new Student() 177 { 178 Id=4, 179 Name="新的世界", 180 ClassId=4, 181 Age=30 182 }, 183 new Student() 184 { 185 Id=4, 186 Name="Rui", 187 ClassId=4, 188 Age=30 189 }, 190 new Student() 191 { 192 Id=4, 193 Name="帆", 194 ClassId=4, 195 Age=30 196 }, 197 new Student() 198 { 199 Id=4, 200 Name="肩膀", 201 ClassId=4, 202 Age=30 203 }, 204 new Student() 205 { 206 Id=4, 207 Name="孤独的根号三", 208 ClassId=4, 209 Age=30 210 } 211 }; 212 #endregion 213 return studentList; 214 }
只要实现了IEnumerable这个接口,都是可以使用 where,Count等方法,只要底层是实现IEnumerable的,都是linq to object
linq To object 是.netFramwork3.0的一个非常重大的改变
下面展示一下linq to object 的几种使用方式
1 #region linq to object Show 2 { 3 Console.WriteLine("********************"); 4 var list = from s in studentList 5 where s.Age < 30 6 select s; 7 8 foreach (var item in list) 9 { 10 Console.WriteLine("Name={0} Age={1}", item.Name, item.Age); 11 } 12 } 13 14 { 15 Console.WriteLine("********************"); 16 var list = studentList.Where<Student>(s => s.Age < 30) 17 .Select(s => new 18 { 19 IdName = s.Id + s.Name, 20 ClassName = s.ClassId == 2 ? "高级班" : "其他班" 21 }); 22 foreach (var item in list) 23 { 24 Console.WriteLine("Name={0} Age={1}", item.ClassName, item.IdName); 25 } 26 } 27 { 28 Console.WriteLine("********************"); 29 var list = from s in studentList 30 where s.Age < 30 31 select new 32 { 33 IdName = s.Id + s.Name, 34 ClassName = s.ClassId == 2 ? "高级班" : "其他班" 35 }; 36 37 foreach (var item in list) 38 { 39 Console.WriteLine("Name={0} Age={1}", item.ClassName, item.IdName); 40 } 41 } 42 { 43 Console.WriteLine("********************"); 44 var list = studentList.Where<Student>(s => s.Age < 30)//条件过滤 45 .Select(s => new//投影 46 { 47 Id = s.Id, 48 ClassId = s.ClassId, 49 IdName = s.Id + s.Name, 50 ClassName = s.ClassId == 2 ? "高级班" : "其他班" 51 }) 52 .OrderBy(s => s.Id)//排序 53 54 .OrderByDescending(s => s.ClassId)//倒排 55 .Skip(2)//跳过几条 56 .Take(3)//获取几条 57 ; 58 foreach (var item in list) 59 { 60 Console.WriteLine($"Name={item.ClassName} Age={item.IdName}"); 61 } 62 } 63 {//group by 64 Console.WriteLine("********************"); 65 var list = from s in studentList 66 where s.Age < 30 67 group s by s.ClassId into sg 68 select new 69 { 70 key = sg.Key, 71 maxAge = sg.Max(t => t.Age) 72 }; 73 foreach (var item in list) 74 { 75 Console.WriteLine($"key={item.key} maxAge={item.maxAge}"); 76 } 77 //group by new {s.ClassId,s.Age} 78 //group by new {A=s.ClassId>1} 79 } 80 { 81 Console.WriteLine("********************"); 82 var list = studentList.GroupBy(s => s.ClassId).Select(sg => new 83 { 84 key = sg.Key, 85 maxAge = sg.Max(t => t.Age) 86 }); 87 foreach (var item in list) 88 { 89 Console.WriteLine($"key={item.key} maxAge={item.maxAge}"); 90 } 91 } 92 List<Class> classList = new List<Class>() 93 { 94 new Class() 95 { 96 Id=1, 97 ClassName="初级班" 98 }, 99 new Class() 100 { 101 Id=2, 102 ClassName="高级班" 103 }, 104 new Class() 105 { 106 Id=3, 107 ClassName="微信小程序" 108 }, 109 }; 110 { 111 var list = from s in studentList 112 join c in classList on s.ClassId equals c.Id 113 select new 114 { 115 Name = s.Name, 116 CalssName = c.ClassName 117 }; 118 foreach (var item in list) 119 { 120 Console.WriteLine($"Name={item.Name},CalssName={item.CalssName}"); 121 } 122 } 123 { 124 var list = studentList.Join(classList, s => s.ClassId, c => c.Id, (s, c) => new 125 { 126 Name = s.Name, 127 CalssName = c.ClassName 128 }); 129 foreach (var item in list) 130 { 131 Console.WriteLine($"Name={item.Name},CalssName={item.CalssName}"); 132 } 133 } 134 {//左连接 135 var list = from s in studentList 136 join c in classList on s.ClassId equals c.Id 137 into scList 138 from sc in scList.DefaultIfEmpty()// 139 select new 140 { 141 Name = s.Name, 142 CalssName = sc == null ? "无班级" : sc.ClassName//c变sc,为空则用 143 }; 144 foreach (var item in list) 145 { 146 Console.WriteLine($"Name={item.Name},CalssName={item.CalssName}"); 147 } 148 Console.WriteLine(list.Count()); 149 } 150 { 151 var list = studentList.Join(classList, s => s.ClassId, c => c.Id, (s, c) => new 152 { 153 Name = s.Name, 154 CalssName = c.ClassName 155 }).DefaultIfEmpty();//为空就没有了 156 foreach (var item in list) 157 { 158 Console.WriteLine($"Name={item.Name},CalssName={item.CalssName}"); 159 } 160 Console.WriteLine(list.Count()); 161 } 162 { 163 164 } 165 #endregion
linq to sql 运用的是表达式目录树,这个底层是实现的IQueryable,概念和linq to object是不一样的!