• Csharp学习Linq


    Linq的学习

    这里继续使用之前文章创建的学生类,首先简单介绍一下linq的使用。

    Student.cs

     public class Student
     {
         public int Id { get; set; }
         public int ClassId { get; set; }
    
         public string Name { get; set; }
    
         public int Age { get; set; }
    
         public string Description { get; set; }
    
         public void Study()
         {
             Console.WriteLine($"{this.Id} {this.Name} 跟着老师学习 .Net开发");
    
         }
    
         public void StudyQt()
         {
             Console.WriteLine($"{this.Id} {this.Name} 跟着老师学习C++ Qt");
         }
     }
    

    初始化学生数据

    public class LinqPrinciple
    {
        private List GetStudentsList()
        {
            List students = new List()
            { new Student() { Id = 1, ClassId = 1, Name = "张三", Age = 20, Description = "张三是一个好学生" },
                 new Student() { Id = 2, ClassId = 1, Name = "李四", Age = 21, Description = "李四是一个好学生" },
                 new Student() { Id = 3, ClassId = 2, Name = "王五", Age = 22, Description = "王五是一个好学生" },
                 new Student() { Id = 4, ClassId = 2, Name = "赵六", Age = 23, Description = "赵六是一个好学生" },
                 new Student() { Id = 5, ClassId = 3, Name = "孙七", Age = 24, Description = "孙七是一个好学生" },
                 new Student() { Id = 6, ClassId = 3, Name = "周八", Age = 25, Description = "周八是一个好学生" },
                  new Student() { Id = 7, ClassId = 1, Name = "绿春", Age = 30, Description = "张三是一个好学生" },
                 new Student() { Id = 8, ClassId = 1, Name = "麻醉", Age = 35, Description = "李四是一个好学生" },
                 new Student() { Id = 9, ClassId = 2, Name = "开天", Age = 26, Description = "王五是一个好学生" },
                 new Student() { Id = 10, ClassId = 2, Name = "匹敌", Age = 22, Description = "赵六是一个好学生" },
                 new Student() { Id = 11, ClassId = 3, Name = "独轮车", Age = 23, Description = "孙七是一个好学生" },
                 new Student() { Id = 12, ClassId = 3, Name = "火箭英", Age = 20, Description = "周八是一个好学生" }
    
            };
            return students;
        }
    }
    

    下面写几个简单的linq的语句,大概知道一下它的使用.

    
       public void  Show()
       {
           //获取一下ClassID为3的学生们
           List students = GetStudentsList();
           List studentsId=students.Where(s => s.ClassId == 3).ToList();
           Console.WriteLine("********************************1*****************************");
           foreach (var student in studentsId)
           {
               Console.WriteLine($"{student.Id} {student.Name} {student.Age} {student.Description}");
           }
           Console.WriteLine("********************************2*****************************");
           //获取一下年纪大于24的学生们
           List studentsAge = students.Where(s => s.Age > 24).ToList();
           foreach (var student in studentsAge)
           {
               Console.WriteLine($"{student.Id} {student.Name} {student.Age} {student.Description}");
           }
           Console.WriteLine("********************************3*****************************");
           //获取一下年纪小于23同时ClassID为2的学生们
           List studentsAgeClassId = students.Where(s => s.Age < 23 && s.ClassId == 2).ToList();
           foreach (var student in studentsAgeClassId)
           {
               Console.WriteLine($"{student.Id} {student.Name} {student.Age} {student.Description}");
           }
       }
    

    linq的原理的探究

    下面尝试探索一下这个linq的本质是什么?

    尝试自己实现一下这3个需求代码,如下

     List students = GetStudentsList();
     List studentsId=new List();
     foreach (var student in students)
     {
         if (student.ClassId == 3)
         {
             studentsId.Add(student);
         }
     }
    
     List studentsAge=new List();
     foreach (var student in students)
     {
         if (student.Age > 24)
         {
             studentsAge.Add(student);
         }
     }
    
     List studentsAgeClassId=new List();
     foreach (var student in students)
     {
         if (student.Age < 23 && student.ClassId == 2)
         {
             studentsAgeClassId.Add(student);
         }
     }
    

    这上面的代码有什么问题?

    大量的重复代码---最好是封装一些,把重复的代码统一封装;

    这里使用一个解决方案

    封装一个方法,将判断的逻辑独立到一个小方法中去.

            public static bool  IsOk01(Student student)
            {
                return student.ClassId == 3;
            }
    
            public static bool IsOk02(Student student)
            {
                return student.Age > 24;
            }
    
            public static bool IsOk03(Student student)
            {
                return student.Age < 23 && student.ClassId == 2;
            }
            public static List DragonWhere(List studentlist,Funcbool> Func)
            {
                List students = new List();
                foreach (var student in studentlist)
                {
                    if (Func(student))
                    {
                        students.Add(student);
                    }
                }
                return students;
            }
    

    尝试使用一下封装的函数

    List students = GetStudentsList();
    List studentId= MethodExtension.DragonWhere(students, MethodExtension.IsOk01);
    

    这里还可以使用扩展方法和lambda表达式进一步的优化我们的代码

          public static List DragonWhere(this List studentlist,Funcbool> Func)
            {
                List students = new List();
                foreach (var student in studentlist)
                {
                    if (Func(student))
                    {
                        students.Add(student);
                    }
                }
                return students;
            }
    

    在调用的时候,

    List students = GetStudentsList();
    List studentsId = students.DragonWhere(s => s.ClassId == 3);
    

    这里就串联上了我们之前学到的知识,最后为了支持多种数据类型,使用上泛型,最后我们就得到了最终封装的方法.

     public static List DragonWhere(this List studentlist,Funcbool> Func)
     {
         List students = new List();
         foreach (var student in studentlist)
         {
             if (Func(student))
             {
                 students.Add(student);
             }
         }
         return students;
     }
    

    这里也要使用ilspy反编译一下它们的实现是如何?

    看起来跟我们自己实现的Where差不多的样子.
    img

    再去看一下它的movenext函数.

    img

    这个就是一个yield return反汇编出来的状态机的代码。

    linq常见的语句

     public void Show()
     {
         List studentList = this.GetStudentList(); 
         #region Linq 扩展方法&表达式
         {  
             var list = studentList.Where(s => s.Age < 30); //list里面必然是符合要求的数据;
             foreach (var item in list)
             {
                 Console.WriteLine("Name={0}  Age={1}", item.Name, item.Age);
             }
         }
         {
             Console.WriteLine("********************");
             var list = from s in studentList
                        where s.Age < 30
                        select s;   //list里面必然是符合要求的数据;
    
             foreach (var item in list)
             {
                 Console.WriteLine("Name={0}  Age={1}", item.Name, item.Age);
             }
         }
         #endregion
    
         #region linq to object Show
         {
             Console.WriteLine("********************");
             var list = studentList.Where(s => s.Age < 30)
                                  .Select(s => new  //投影:可以做一些自由组装+ new 一个匿名类,也可以new 具体类;
                                  {
                                      IdName = s.Id + s.Name,
                                      ClassName = s.ClassId == 2 ? "高级班" : "其他班"
                                  });
             foreach (var item in list)
             {
                 Console.WriteLine("Name={0}  Age={1}", item.ClassName, item.IdName);
             }
         }
         {
             Console.WriteLine("********************");
             var list = from s in studentList
                        where s.Age < 30
                        select new
                        {
                            IdName = s.Id + s.Name,
                            ClassName = s.ClassId == 2 ? "高级班" : "其他班"
                        };
    
             foreach (var item in list)
             {
                 Console.WriteLine("Name={0}  Age={1}", item.ClassName, item.IdName);
             }
         }
         {
             Console.WriteLine("********************");
             var list = studentList.Where(s => s.Age < 30)//条件过滤
                                  .Select(s => new//投影
                                  {
                                      Id = s.Id,
                                      ClassId = s.ClassId,
                                      IdName = s.Id + s.Name,
                                      ClassName = s.ClassId == 2 ? "高级班" : "其他班"
                                  })
                                  .OrderBy(s => s.Id)//排序 升序
                                  .ThenBy(s => s.ClassName) //多重排序,可以多个字段排序都生效
                                  .OrderByDescending(s => s.ClassId)//倒排
                                  .Skip(2)//跳过几条  //必须要先排序
                                  .Take(3)//获取几条 //必须要先排序
                                  ;
             foreach (var item in list)
             {
                 Console.WriteLine($"Name={item.ClassName}  Age={item.IdName}");
             }
         }
         {//group by·
             Console.WriteLine("********************");
             var list = from s in studentList
                        where s.Age < 30
                        group s by s.ClassId into sg
                        select new
                        {
                            key = sg.Key,
                            maxAge = sg.Max(t => t.Age)
                        };
             foreach (var item in list)
             {
                 Console.WriteLine($"key={item.key}  maxAge={item.maxAge}");
             }
             //group by new {s.ClassId,s.Age}
             //group by new {A=s.ClassId>1}
         }
         {
             Console.WriteLine("********************");
             var list = studentList.GroupBy(s => s.ClassId).Select(sg => new
             {
                 key = sg.Key,
                 maxAge = sg.Max(t => t.Age)
             });
             foreach (var item in list)
             {
                 Console.WriteLine($"key={item.key}  maxAge={item.maxAge}");
             }
         }
         {
             var list = studentList.GroupBy(s => s.ClassId);
             foreach (var date in list) ///实现了IEnumerable
             {
                 Console.WriteLine(date.Key);
    
                 foreach (var item in date)
                 {
                     Console.WriteLine(item.Age);
                 }
    
             }
    
         }
         List classList = new List()
             {
                 new Class()
                 {
                     Id=1,
                     ClassName="架构班"
                 },
                 new Class()
                 {
                     Id=2,
                     ClassName="高级班"
                 },
                 new Class()
                 {
                     Id=3,
                     ClassName="全栈班"
                 },
             };
         {
    
             //Join 
             var list = from s in studentList
                        join c in classList on s.ClassId equals c.Id  //只能使用equals  不能使==
                        select new
                        {
                            Name = s.Name,
                            CalssName = c.ClassName
                        };
             foreach (var item in list)
             {
                 Console.WriteLine($"Name={item.Name},CalssName={item.CalssName}");
             }
         }
         {
             var list = studentList.Join(classList, s => s.ClassId, c => c.Id, (s, c) => new
             {
                 Name = s.Name,
                 CalssName = c.ClassName
             });
             foreach (var item in list)
             {
                 Console.WriteLine($"Name={item.Name},CalssName={item.CalssName}");
             }
         }
         {//左连接
             var list = from s in studentList
                        join c in classList on s.ClassId equals c.Id
                        into scList
                        from sc in scList.DefaultIfEmpty()//
                        select new
                        {
                            Name = s.Name,
                            CalssName = sc == null ? "无班级" : sc.ClassName//c变sc,为空则用
                        };
             foreach (var item in list)
             {
                 Console.WriteLine($"Name={item.Name},CalssName={item.CalssName}");
             }
             Console.WriteLine(list.Count());
         }
         {
             var list = studentList.Join(classList, s => s.ClassId, c => c.Id, (s, c) => new
             {
                 Name = s.Name,
                 CalssName = c.ClassName
             }).DefaultIfEmpty();//为空就没有了
             foreach (var item in list)
             {
                 Console.WriteLine($"Name={item.Name},CalssName={item.CalssName}");
             }
             Console.WriteLine(list.Count());
         }
         {
    
             //左连接和右链接  就是链接对象交换一下即可;
    
         }
         #endregion
     }
    
  • 相关阅读:
    常用的Linux命令
    does not export com.sun.tools.javac.util to unnamed moudle
    C++ QT QLocalSocket/QLocalServer基操
    获取系统参数System.getProperties()与配置文件参数@Value(“${key}“)
    【华为机试真题 JAVA】数据分类-200
    My Seventy-ninth Page - 完全平方数 - By Nicolas
    Linux 链表示例 LIST_INIT LIST_INSERT_HEAD
    Coursera自动驾驶1.5——纵向控制
    P1154 奶牛分厩
    细节决定成败,这3点值得你们深思
  • 原文地址:https://www.cnblogs.com/wenlong-4613615/p/18073134