原始写法:
//原始方法
var list = new List<Student>();
foreach (var item in students)
{
if (item.Age <40 &&item.Id>1 )
{
Console.WriteLine($"{item.Name}的年龄是{item.Age}!");
}
}
书写 Linq 的两种方式
var students = new List<Student>()
{
new Student{ Id=1,Name="张三",Age=23},
new Student{ Id=1,Name="李四",Age=30},
new Student{ Id=1,Name="王麻子",Age=50},
new Student{ Id=1,Name="周扒皮",Age=60},
};
var res = students.Where(x => x.Age < 40);
//语法糖:
var res1 = from x in students where x.Age < 40 select x;
在以往像下面这样的方法可能不能满足需求:当条件变多的时候就尴尬了
public List<Student> StudentQuery( List<Student> list)
{
var res = new List<Student>();
foreach (var item in list)
{
if (item.Age < 40 && item.Id > 1)
{
res .Add(item);
}
}
return res ;
}
进阶:委托版本:
public List<Student> StudentQuery( List<Student> list,Func<Student ,bool> isTarget)
{
var res = new List<Student>();
foreach (var item in list)
{
if (isTarget.Invoke(item)) {
res.Add(item);
}
}
return res;
}
调用委托上面的方法:
var data = ExtendStudents.StudentQuery(list, x => x.Id > 1 && x.Age < 40);
最后将委托版本的方法改为 拓展方法 再调用: 现在的格式就类似 Linq 表达式了
public static List<Student> StudentQuery(this List<Student> list,Func<Student ,bool> isTarget)
{
var res = new List<Student>();
foreach (var item in list)
{
if (isTarget.Invoke(item)) {
res.Add(item);
}
}
return res;
}
var data = list.StudentQuery(x => x.Id > 1 && x.Age < 40);
再进阶: 泛型版本
public static class ExtendStudents
{
public static List<T> StudentQuery<T>(this List<T> list,Func<T, bool> isTarget)
{
var res = new List<T>();
foreach (var item in list)
{
if (isTarget.Invoke(item)) {
res.Add(item);
}
}
return res;
}
}
调用方式不变:
var data = list.StudentQuery(x => x.Id > 1 && x.Age < 40);
还可以给其他的List使用:
var intList = new List<int> { 456,1431,8 ,545,78,64,96 }
var data1 = intList.StudentQuery(x => x > 500);
再进阶: 泛型版本+迭代器
public static IEnumerable<T> Query<T>(this IEnumerable<T> list, Func<T, bool> isTarget)
{
foreach (var item in list)
{
if (isTarget.Invoke(item))
{
yield return item; //yield 与 IEnumberable 配对使用
}
}
}
调用示例:
var intList = new List<int> { 456, 1431, 8, 545, 78, 64, 96 };
var data1 = intList.Query(x => x > 500);
注意:yield 与 IEnumberable 配对使用,List 是不能只用 yeild 关键字的
迭代器版本,与上面的非迭代器版本的区别
方法代码:
public static class ExtendStudents
{
//非迭代版本
public static List<T> OldQuery<T>(this List<T> list,Func<T, bool> isTarget)
{
var res = new List<T>();
foreach (var item in list)
{
Console.WriteLine("休息0.1秒");
Thread.Sleep(100);
if (isTarget.Invoke(item)) {
res.Add(item);
}
}
return res;
}
//迭代版本
public static IEnumerable<T> YieldQuery<T>(this IEnumerable<T> list, Func<T, bool> isTarget)
{
foreach (var item in list)
{
Console.WriteLine("休息0.1秒");
Thread.Sleep(100);
if (isTarget.Invoke(item))
{
yield return item;
}
}
}
}
调用:
static void Main(string[] args)
{
var intList = new List<int> { 456, 1431, 8, 545, 78, 64, 96,78,89,456,456,12,45,2,5,4,6456,45,564,45,545,21,213, };
Console.WriteLine("**************非迭代器版本");
var data1 = intList.OldQuery(x => x > 500);
foreach (var item in data1)
{
Console.WriteLine($"我是数字:{item}");
}
Console.WriteLine("**************迭代器版本");
var data2 = intList.YieldQuery(x => x > 500);
foreach (var item in data2)
{
Console.WriteLine($"我是数字:{item}");
}
Console.Read();
}
效果:
断点截图:所以有了迭代器的效果就是按需加载,没有迭代器的 foreach 是 全部过滤完才便利
以上就是 Where 方法 手动的实现 ,现在用反编译工具看一下 where 方法的源码:
这里有对数据和委托的非空判断
这上面都会判断有没有迭代器, 数组,list 即便没有迭代器, 也会使用方法让它用上迭代器 就像上边的
WhereArrayIterator
WhereListIterator
说起来
Lamada 表达式 是 委托的参数 /匿名方法
Link 是一个封装的工具类库 ,
类库中大量使用了 委托 ,要说关系这就是关系