Csharp学习Linq

  • Csharp学习Linq已关闭评论
  • 38 次浏览
  • A+
所属分类:.NET技术
摘要

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


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 void  Show()    {        //获取一下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 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<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差不多的样子.
Csharp学习Linq

再去看一下它的movenext函数.

Csharp学习Linq

这个就是一个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  }