• 手写Linq To Object


    1、数据准备

    public class Student
    {
        public string Name { get; set; }
    
        public int Age { get; set; }
    }
    
    var studentList = new List<Student>();
    Student student1 = new Student();
    student1.Name = "张三";
    student1.Age = 30;
    
    Student student2 = new Student();
    student2.Name = "李四";
    student2.Age = 29;
    
    Student student3 = new Student();
    student3.Name = "赵春来";
    student3.Age = 28;
    
    studentList.Add(student1);
    studentList.Add(student2);
    studentList.Add(student3);

    2、看看Where是什么?
    studentList.Where是接受泛型继承IEnumerable类型的数据源,和接受泛型类型返回布尔值的委托,返回IEnumerable类型的扩展方法

    3、原始写法

    a、foreash 遍历集合得写两遍
    b、添加到结果集合得写两遍
    不同的是查询条件不同

    //查找年龄小于30的学生
    {
        var list = new List<Student>();
        foreach (var item in studentList)
        {
            if (item.Age < 30)
            {
                list.Add(item);
            }
        }
    }
    //查找姓名大于2个字的学生
    {
        var list = new List<Student>();
        foreach (var item in studentList)
        {
            if (item.Name.Length > 2)
            {
                list.Add(item);
            }
        }
    }

    4、第一次封装Linq To Object

    a、把集合传递进去
    b、把查询条件传递进去--返回布尔值的委托

    //1、调用第一次封装Linq to Object
    CustomerWhereOne(studentList, ((s) => s.Age < 30));
    CustomerWhereOne(studentList, new Func<Student, bool>(s => s.Name.Length > 2));
    
    /// <summary>
    /// 1、第一次封装Linq To Object
    /// </summary>
    /// <param name="resource">数据源</param>
    /// <param name="func">返回布尔值的委托</param>
    public static List<Student> CustomerWhereOne(List<Student> resource, Func<Student, bool> func)
    {
        var result = new List<Student>();
        foreach (var item in resource)
        {
            if (func(item))
            {
                result.Add(item);
            }
        }
    
        return result;
    }

    5、第二次封装Linq To Object
    a、改为泛型--List<T>
    b、改为扩展方法

    //2、调用第二次封装Linq To Object
    {
        var resultList = studentList.CustomerWhereTwo((s) => s.Age < 30);
        var resultList2 = studentList.CustomerWhereTwo(new Func<Student, bool>(s => s.Name.Length > 2));
    
        foreach (var item in resultList)
        {
            Console.WriteLine(item.Name);
        }
    }
    
    /// <summary>
    /// 2、第二次封装Linq To Object,改为泛型,改为扩展方法
    /// </summary>
    /// <param name="resource">数据源</param>
    /// <param name="func">返回布尔值的委托</param>
    public static List<T> CustomerWhereTwo<T>(this List<T> resource, Func<T, bool> func)
    {
        var result = new List<T>();
        foreach (var item in resource)
        {
            if (func(item))
            {
                result.Add(item);
            }
        }
    
        return result;
    }

    6、第三次封装Linq To Object,改为yield迭代器模式,完成了数据的按需获取,延迟加载
    yield和IEnumerable配合使用
    a、返回值类型改为IEnumerable
    b、return前面加yield

    //3、调用第三次封装Linq to Object
    {
        var resultList = studentList.CustomerWhereThree((s) => s.Age < 30);
        var resultList2 = studentList.CustomerWhereThree(new Func<Student, bool>(s => s.Name.Length > 2));
        foreach (var item in resultList)
        {
            Console.WriteLine(item.Name);
        }
    }
    
    /// <summary>
    /// 3、第三次封装Linq To Object,改为迭代器模式,完成了数据的按需获取,延迟加载
    /// </summary>
    /// <param name="resource">数据源</param>
    /// <param name="func">返回布尔值的委托</param>
    public static IEnumerable<T> CustomerWhereThree<T>(this IEnumerable<T> resource, Func<T, bool> func)
    {
        var result = new List<T>();
        foreach (var item in resource)
        {
            if (func(item))
            {
                yield return item;
            }
        }
    }

    调试代码,我们发现resultList返回的是个ResultView,且提示当展开结果视图枚举IEnumerable

    只有当真正使用,去遍历的时候才去调用真正去调用CustomerWhereThree

    至此我们通过一步步封装了一个和内置Where一样的CustomerWhereThree方法--Linq To Object

    • 总结

    1、Linq是基于委托的封装(例子中的--func),逻辑解耦(查询条件可变化的部分传递进去 --s.Age < 30和s.Name.Length > 2),代码重用(把循环遍历集合和添加到结果集这样的动作封装了起来--foreach (var item in resource))。
    2、IEnumerable--yield--利用的迭代器的延迟,按需获取。

  • 相关阅读:
    MVC中的helper标签
    自适应网页设计(Responsive Web Design)
    网站设计的最简主义
    Windows Forms数据绑定技术
    [C#]写自己的类库
    C#数据库连接字符串
    CSS float属性
    CSS之UL
    NET教程:MVC4使用Bundling,CSS中图片路径问题
    ASP.net 中Get和Post的用法
  • 原文地址:https://www.cnblogs.com/menglin2010/p/12583666.html
Copyright © 2020-2023  润新知