段小非 发表于 2024-3-19 10:38:37

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<Student> GetStudentsList()
    {
      List<Student> students = new List<Student>()
      { 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 voidShow()
   {
       //获取一下ClassID为3的学生们
       List<Student> students = GetStudentsList();
       List<Student> 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<Student> 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<Student> 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<Student> students = GetStudentsList();
List<Student> studentsId=new List<Student>();
foreach (var student in students)
{
   if (student.ClassId == 3)
   {
         studentsId.Add(student);
   }
}

List<Student> studentsAge=new List<Student>();
foreach (var student in students)
{
   if (student.Age > 24)
   {
         studentsAge.Add(student);
   }
}

List<Student> studentsAgeClassId=new List<Student>();
foreach (var student in students)
{
   if (student.Age < 23 && student.ClassId == 2)
   {
         studentsAgeClassId.Add(student);
   }
}这上面的代码有什么问题?
大量的重复代码---最好是封装一些,把重复的代码统一封装;
这里使用一个解决方案
封装一个方法,将判断的逻辑独立到一个小方法中去.
      public static boolIsOk01(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<Student> DragonWhere(List<Student> studentlist,Func<Student,bool> Func)
      {
            List<Student> students = new List<Student>();
            foreach (var student in studentlist)
            {
                if (Func(student))
                {
                  students.Add(student);
                }
            }
            return students;
      }尝试使用一下封装的函数
List<Student> students = GetStudentsList();
List<Student> studentId= MethodExtension.DragonWhere(students, MethodExtension.IsOk01);这里还可以使用扩展方法和lambda表达式进一步的优化我们的代码
      public static List<Student> DragonWhere(this List<Student> studentlist,Func<Student,bool> Func)
      {
            List<Student> students = new List<Student>();
            foreach (var student in studentlist)
            {
                if (Func(student))
                {
                  students.Add(student);
                }
            }
            return students;
      }在调用的时候,
List<Student> students = GetStudentsList();
List<Student> studentsId = students.DragonWhere(s => s.ClassId == 3);这里就串联上了我们之前学到的知识,最后为了支持多种数据类型,使用上泛型,最后我们就得到了最终封装的方法.
public static List<T> DragonWhere<T>(this List<T> studentlist,Func<T,bool> Func)
{
   List<T> students = new List<T>();
   foreach (var student in studentlist)
   {
         if (Func(student))
         {
             students.Add(student);
         }
   }
   return students;
}这里也要使用ilspy反编译一下它们的实现是如何?
看起来跟我们自己实现的Where差不多的样子.

再去看一下它的movenext函数.

这个就是一个yield return反汇编出来的状态机的代码。
linq常见的语句

public void Show()
{
   List<Student> studentList = this.GetStudentList();
   #region Linq 扩展方法&表达式
   {
         var list = studentList.Where<Student>(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<Student>(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<Student>(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<Class> classList = new List<Class>()
         {
             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
}
来源:https://www.cnblogs.com/wenlong-4613615/p/18073134
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: Csharp学习Linq