Linq 一、 Linq 的诞生过程--迭代器的好处

原始写法:

 //原始方法
            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 是一个封装的工具类库  ,

类库中大量使用了 委托 ,要说关系这就是关系

猜你喜欢

转载自blog.csdn.net/qq_36445227/article/details/90748391