zoukankan      html  css  js  c++  java
  • c# linq查询语句详细使用介绍

    本文介绍Linq的使用方法

    1. linq介绍

      LINQ只不过是实现IEnumerable和IQueryable接口的类的扩展方法的集合。
      LINQ可以查询IEnumerable集合或者IQueryable数据源
          查询语法
              List<string> list = new List<string>() { "a", "b", "cb", "d", "e" };
              var result = from s in list where s.Contains("b") select s;
          方法语法
              方法语法的使用就是调用Enumberable或者Queryable的扩展方法
              List<string> list = new List<string>() { "a", "b", "cb", "dc", "e" };
              var result = list.Where(s => s.Contains("c"));
              上面Where中传递的是一个lambda表达式是匿名函数的简写形式,完整写法如下
                  var result = list.Where(delegate (string s) {
                      return s.Contains("c");
                  });
      
    2. 标准的查询操作符

      ** 过滤操作符
          > Where操作符
              在查询语句中使用where在后面加上过滤条件(函数)就可以了
                  List<string> list = new List<string>() { "a", "b", "cb", "dc", "ae" };
                  Func<string, bool> isFilter = s => s.Contains("a");
                  var result = from s in list where isFilter(s) select s;
              在扩展方法中使用where有两个重载 
                  不带索引的重载
                      List<string> list = new List<string>() { "a", "b", "cb", "dc", "e" };
                      var result = list.Where(s => s.Contains("c"));
                  带索引的重载
                      List<string> list = new List<string>() { "a", "b", "cb", "dc", "e" };
                      int isum = 0;
                      IEnumerable<string> result = list.Where((s, i) =>
                      {
                          if (s.Contains("c"))
                          {
                              isum++;
                              return true;
                          }
                          return false;
                      }).ToList(); // 这里不写ToList()的话linq语句不执行
                      return Ok(isum);
              无论是查询语句还是扩展方法,where都可以使用多个
                  IEnumerable<string> result = list.Where(s => s.Contains("c")).Where(s => s.Contains("b"));
          > OfType操作符
              使用OfType操作符可以根据数据类型来过滤数据
              在查询语句中使用
                  ArrayList list = new ArrayList() { 2, "a", 5};
                  var result = from s in list.OfType<int>() select s; // 将ArrayList所有的int类型数据筛选出来
              在扩展方法中使用
                  ArrayList list = new ArrayList() { 2, "a", 5};
                  var result = list.OfType<string>();
      ** 排序操作符
          > OrderBy语句
              根据指定的字段升序或者降序排序
              IList<TestClass> list = new List<TestClass>() {
                  new TestClass() { StudentID = 1, StudentName = "John", Age = 18 } ,
                  new TestClass() { StudentID = 2, StudentName = "Steve",  Age = 15 } ,
                  new TestClass() { StudentID = 3, StudentName = "Bill",  Age = 15 } ,
                  new TestClass() { StudentID = 4, StudentName = "Ram" , Age = 20 } ,
                  new TestClass() { StudentID = 5, StudentName = "Ron" , Age = 19 }
              };
              在查询语句中使用
                  var result = from s in list orderby s.Age select s; // 默认是升序排序,ascending可以指定也可以不写
                  var result = from s in list orderby s.Age descending select s; // 指定descending实现降序
                  可以指定多条列进行排序
                      var result = from s in list orderby s.Age, s.StudentID descending select s;
                      如果s.Age是相同的,那么根据s.StudentID对相同的数据进行排序
              在扩展语句中使用
                  重载一,使用默认规则实现简单的升序排序
                      var result = list.OrderBy(s => s.Age); // 根据Age字段进行升序排序,不支持降序
                  重载二,可以传递IComparer泛型实例,实现自定义排序规则
                      先定义一个实现IComparer的类
                          public class CompareClass : IComparer<string>
                          {
                              public int Compare(string x, string y)
                              {
                                  string str1 = x.Substring(1, 1);
                                  string str2 = y.Substring(1, 1);
                                  return int.Parse(str1).CompareTo(int.Parse(str2)); // 升序,如果调换str1和str2的位置,可以实现降序
                              }
                          }
                      实现排序
                          IList<TestClass> list = new List<TestClass>() {
                              new TestClass() { StudentID = 1, StudentName = "A3_John", Age = 18 } ,
                              new TestClass() { StudentID = 2, StudentName = "A4_Steve",  Age = 15 } ,
                              new TestClass() { StudentID = 3, StudentName = "A2_Bill",  Age = 25 } ,
                              new TestClass() { StudentID = 4, StudentName = "A5_Ram" , Age = 20 } ,
                              new TestClass() { StudentID = 5, StudentName = "A6_Ron" , Age = 19 }
                          };
                          var result = list.OrderBy(s => s.StudentName, new CompareClass());
          > OrderByDescending语句
              根据指定的字段降序排序,只能在扩展方法中使用
              var result = list.OrderByDescending(s => s.Age);
          > ThenBy语句
              用于二级排序的升序,只能在扩展方法中使用
              var result = list.OrderBy(s => s.Age).ThenBy(s => s.StudentID);
              对s.Age排序后的结果中的相同项按照s.StudentID进行升序排序
          > ThenByDescending语句
              用于二级排序的降序,只能在扩展方法中使用
              var result = list.OrderBy(s => s.Age).ThenByDescending(s => s.StudentID);
              对s.Age排序后的结果中的相同项按照s.StudentID进行降序排序
          > Reverse语句
              反序排序,只能用于扩展方法中
              var result = list.Reverse();
              对原始集合进行反转排序操作
      ** 分组操作符
          > GroupBy操作符
              GroupBy根据指定的列将相同项分成一组,返回的结果是IEnumerable <IGrouping<TKey, TSource>>类型
              每组是IGrouping<TKey, TSource>类型,TKey是键的类型,TSource是结果集合的类型
              IList<TestClass> list = new List<TestClass>() {
                  new TestClass() { StudentID = 1, StudentName = "A3_John", Age = 18 } ,
                  new TestClass() { StudentID = 2, StudentName = "A4_Steve",  Age = 15 } ,
                  new TestClass() { StudentID = 3, StudentName = "A2_Bill",  Age = 15 } ,
                  new TestClass() { StudentID = 4, StudentName = "A5_Ram" , Age = 20 } ,
                  new TestClass() { StudentID = 5, StudentName = "A6_Ron" , Age = 20 }
              };
              在查询语句中使用
                  var result = from s in list group s by s.Age;
                  foreach(var ageGroup in result)
                  {
                      Trace.WriteLine(ageGroup.Key); // Key是分组的Age值
                      foreach( TestClass s in ageGroup)
                      {
                          // ...
                      }   
                  }
              在扩展方法中使用
                  var result = list.GroupBy(s => s.Age);
          > ToLookup操作符
              只能在扩展方法中使用
                  var result = list.ToLookup(s => s.Age);
                  ToLookup和GroupBy功能是一样的,但是ToLookup是立即执行的,而GroupBy之后的result是没有值的,只会在使用的时候执行并存储数据
      ** 连接操作符
          > Join操作符
              作用和sql的 inner Join 一样
              在扩展方法中使用
                  例子一:
                      第一个参数是inner表,第二个参数是outer表的列,第三个参数是inner表的列,第四个参数是结果集的格式
                      当第二个参数和第三个参数对应的列值相同,那么数据筛选出来,然后经过第四个参数处理后返回
                      List<string> list1 = new List<string>() { "a", "b", "c", "d", "e" };
                      List<string> list2 = new List<string>() { "a", "b", "e", "f", "a" };
                      var result = list1.Join(list2, s1 => s1, s2 => s2, (s1, s2) => s1);
                  例子二:
                      IList<Demo1> studentList1 = new List<Demo1>() {
                          new Demo1() { StudentID = 1, StudentName = "John", StandardID =1 },
                          new Demo1() { StudentID = 2, StudentName = "Moin", StandardID =1 },
                          new Demo1() { StudentID = 3, StudentName = "Bill", StandardID =2 },
                          new Demo1() { StudentID = 4, StudentName = "Ram" , StandardID =2 },
                          new Demo1() { StudentID = 5, StudentName = "Ron"  }
                      };
                      IList<Demo2> standardList2 = new List<Demo2>() {
                          new Demo2(){ StandardID = 1, StandardName="Standard 1"},
                          new Demo2(){ StandardID = 2, StandardName="Standard 2"},
                          new Demo2(){ StandardID = 3, StandardName="Standard 3"}
                      };
                      var result = studentList1.Join(standardList2, s1 => s1.StandardID, s2 => s2.StandardID, (s1, s2) =>
                      {
                          return new
                          {
                              StudentName = s1.StudentName,
                              StandardName = s2.StandardName
                          };
                      });
              在查询语句中使用
                  使用上面的studentList1和standardList2为例
                      var result = from s1 in studentList1
                           join s2 in standardList2 on s1.StandardID equals s2.StandardID
                           select new
                           {
                               StudentName = s1.StudentName,
                               standardName = s2.StandardName
                           };
          > GroupJoin操作符
              作用和sql的 left join,right join类似
              在扩展方法中使用
                  还是使用上面的studentList1和standardList2为例
                  var result = studentList1.GroupJoin(standardList2, s1 => s1.StandardID, s2 => s2.StandardID, (s1, s2Obj) =>
                  {
                      return new
                      {
                          studentName = s1.StudentName,
                          standardName = s2Obj // s2Obj自动将 s2 转成 IEnumerable类型
                      };
                  });
              在查询语句中使用
                  var result = from s1 in studentList1
                               join s2 in standardList2 on s1.StandardID equals s2.StandardID into s3
                               select new
                               {
                                   standard = s3,
                                   studentName = s1.StudentName
                               };
      ** 投影操作符
          > select操作符
              和sql中的select类似
              在查询语句中使用
                  var result = from item in someList select item;
                  var result = from item in someList select new { column1 = item.Name, column2 = item.Age };
              在扩展方法中使用
                  在扩展方法中Select方法仅仅用来格式化数据,在查询数据时是可选项
                  var result = list.Select(s => new
                  {
                      Name = s.StudentName,
                      Age = s.Age
                  });
          > SelectMany方法
              SelectMany方法只能在扩展方法中使用
              SelectMany的作用是将指定列对应的IEnumerable列值合并成一个集合,用法如下
                  定义两个类
                      public class Students
                      {
                          public string Name { get; set; }
                          public int Age { get; set; }
                      }
                      public class ClassNames
                      {
                          public IEnumerable<Students> students { get; set; }
                          public string Name { get; set; }
                      }
                  使用SelectMany
                      List<ClassNames> selectManyTest = new List<ClassNames>() { };
                      selectManyTest.Add(new ClassNames() { students = new List<Students>() { new Students() { Name = "小张", Age = 11 } }, Name = "班级一" });
                      selectManyTest.Add(new ClassNames() { students = new List<Students>() { new Students() { Name = "小王", Age = 21 } }, Name = "班级二" });
                      selectManyTest.Add(new ClassNames() { students = new List<Students>() { new Students() { Name = "小红", Age = 22 } }, Name = "班级三" });
                      var result = selectManyTest.SelectMany(s => s.students);
                  result的结果 [{"Name":"小张","Age":11},{"Name":"小王","Age":21},{"Name":"小红","Age":22}]
                  这种用法其实和Select的作用是一致的 var result = selectManyTest.Select(s => s.students); 关键是下面的这种用法
                  var result = selectManyTest.SelectMany(s => s.students, (s1, s2) =>
                  {
                      return new
                      {
                          班级名称 = s1.Name,
                          学生姓名 = s2.Name,
                          学生年龄 = s2.Age
                      };
                  }); 
                  结果是 [{"班级名称":"班级一","学生姓名":"小张","学生年龄":11},{"班级名称":"班级二","学生姓名":"小王","学生年龄":21},{"班级名称":"班级三","学生姓名":"小红","学生年龄":22}]
                  从这里可以看出SelectMany的优势是将嵌套的复杂类型综合到一个集合中
      ** 量词操作符
          IList<TestClass> studentList = new List<TestClass>() {
              new TestClass() { StudentID = 1, StudentName = "John", Age = 18 } ,
              new TestClass() { StudentID = 2, StudentName = "Steve",  Age = 15 } ,
              new TestClass() { StudentID = 3, StudentName = "Bill",  Age = 25 } ,
              new TestClass() { StudentID = 4, StudentName = "Ram" , Age = 20 } ,
              new TestClass() { StudentID = 5, StudentName = "Ron" , Age = 19 }
          };
          > ALL操作符
              指定筛选条件如果元素全部满足则返回true
              bool result = studentList.All(s => s.Age > 18 && s.Age < 20); // false
          > Any操作符
              指定筛选条件只要有一个满足就返回true
              bool result = studentList.Any(s => s.Age > 18 && s.Age < 20); // true
          > Contains操作符
              值类型用法
                  List<int> list = new List<int>() { 1, 2, 3, 4, 5 };
                  bool result = list.Contains(4);
              引用类型用法
                  引用类型默认比较的是引用,如果要实现自定义比较引用类型,就要实现一个IEqualityComparer类
                  创建一个IEqualityComparer类
                      public class StudentComparer : IEqualityComparer<TestClass>
                      {
                          public bool Equals(TestClass x, TestClass y)
                          {
                              if (x.StudentID == y.StudentID &&
                                  x.StudentName.ToLower() == y.StudentName.ToLower() &&
                                  x.Age == y.Age)
                              {
                                  return true;
                              }
                              return false;
                          }
                          public int GetHashCode(TestClass obj)
                          {
                              Trace.WriteLine(obj.GetHashCode());
                              return obj.GetHashCode();
                          }
                      }
                  使用
                      bool result = studentList.Contains(new TestClass() { StudentID = 2, StudentName = "Steve", Age = 15 }, new StudentComparer()); // true
      ** 聚合操作符
          在linq中聚合函数不能直接使用在查询语句中,但是可以像下面这种方式使用
          var result = (from s in studentList where s.Age > 20 select s).Average(s => s.Age);
          > Aggregate操作符
              用来累积结果
              重载一
                  List<string> list = new List<string> { "a", "b", "c", "d" };
                  var result = list.Aggregate((s1, s2) =>
                  {
                      return s1 + s2;
                  }); // "abcd"
              重载二,需要一个seed作为初始值
                  List<string> list = new List<string> { "a", "b", "c", "d" };
                  var result = list.Aggregate("结果是:", (s1, s2) =>
                  {
                      return s1 + s2;
                  }); // "结果是:abcd"
              重载三,需要一个Func代理函数用来对计算的结果做处理
                  List<string> list = new List<string> { "a", "b", "c", "d" };
                  var result = list.Aggregate(String.Empty, (s1, s2) =>
                  {
                      return s1 += s2 + ",";
                  }, res => res.Substring(0, res.Length - 1)); // "a,b,c,d"
          > Average操作符
              用来计算集合中的数字值的平均值
              计算由数字组成的集合的平均值
                  List<int> list = new List<int>() { 1, 2, 3, 4, 5 };
                  var result = list.Average();
              传递lambda表达式,用来计算引用类型中的数字的平均值
                  var result = studentList.Average(s => s.Age);
          > Count操作符
              返回集合的元素的个数
                  var result = studentList.Count();
              返回满足给定条件的元素个数
                  var result = studentList.Count(s => s.Age > 19);
          > Max操作符
              返回数字集合的最大值
                  List<int> list = new List<int>() { 1, 2, 3, 7, 4, 5, 6 };
                  var result = list.Max(); // 最大值 7
                  var result = list.Max(s => s * 2); // 将元素乘2后计算最大值,14
              返回引用类型集合数字属性的最大值
                  var result = studentList.Max(s => s.Age);
              对于引用类型可以实现自定义的Max比较
                  先声明一个类,实现了 IComparable 接口
                      public class TestClass: IComparable<TestClass>
                      {
                          public int StudentID { get; set; }
                          public string StudentName { get; set; }
                          public int Age { get; set; }
                          public int CompareTo(TestClass other) // 用来筛选出StudentName长度最长的一项
                          {
                              if(this.StudentName.Length >= other.StudentName.Length)
                              {
                                  return 1;
                              }
                              return 0;
                          }
                      }
                  使用
                      IList<TestClass> studentList = new List<TestClass>() {
                          new TestClass() { StudentID = 1, StudentName = "John", Age = 18 } ,
                          new TestClass() { StudentID = 2, StudentName = "Steve",  Age = 15 } ,
                          new TestClass() { StudentID = 3, StudentName = "Bill",  Age = 25 } ,
                          new TestClass() { StudentID = 4, StudentName = "Ram" , Age = 20 } ,
                          new TestClass() { StudentID = 5, StudentName = "Ron" , Age = 19 }
                      };
                      var result = studentList.Max(); // 直接调用Max即可
              Min的使用方式和Max是一直的,不再赘述
          > Sum操作符
              返回数字集合的总和
                  List<int> list = new List<int>() { 1, 2, 3, 7, 4, 5, 6 };
                  var result = list.Sum(); // 返回总和
                  var result = list.Sum(s => s * 2 + 1); // 返回每一项乘2加1后的总和
              返回应用类型集合数字属性的总和
                  var result = studentList.Sum(s => s.Age); // 计算年龄的总和
                  var result = studentList.Sum(s => {
                      if(s.Age > 18)
                      {
                          return 1;
                      }
                      return 0;
                  }); // 计算年龄大于18的人数
      ** 元素操作符
          List<int> intList = new List<int>() { 10, 21, 30, 45, 50, 87 };
          > ElementAt操作符
              根据索引找出元素,超出范围会报错
              var result = intList.ElementAt(1); 
          > ElementAtOrDefault操作符
              根据索引找出元素,超出范围返回默认值,整数默认值是0,字符串默认值是null
              var result = intList.ElementAtOrDefault(9); 
          > First操作符
              返回第一个元素或者第一个满足条件的元素,如果给定的集合是空的,或者没有一个元素满足条件,那么会报错
              var result = intList.First(); // 返回集合中的第一个元素
              var result = intList.First(s => s > 30); // 返回满足条件的第一个元素
              Last的用法和First一致
          > FirstOrDefault操作符
              返回第一个元素或者第一个满足条件的元素,如果给定的集合是空的,或者没有一个元素满足条件那么返回默认值
              用法和上面一样
              LastOrDefault的用法和FirstOrDefault一致
          > Single操作符
              返回集合中的唯一一个元素,或者指定条件后唯一一个元素,如果没有元素或者多于一个元素那么报错
              List<int> intList = new List<int>() { 10 };
              var result = intList.Single();
          > SingleOrDefault操作符
              作用和Single类似,如果没有找到元素,那么返回默认值,然而,如果有多个元素那么同样报错
              List<int> intList = new List<int>() { 10,20 };
              var result = intList.SingleOrDefault(s => s > 10);
      ** 相等运算符
          > SequenceEqual
              用于比较两个集合中的元素是否相等,如果元素是值类型,那么比较元素的值和顺序,如果是引用类型那么比较值的引用
              值类型比较
                  List<int> intList1 = new List<int>() { 10,20 };
                  List<int> intList2 = new List<int>() { 10, 20 };
                  var result = intList1.SequenceEqual(intList2); // true
              引用类型比较  
                  List<TestClass> TestList1 = new List<TestClass>() { new TestClass() { StudentID = 1, StudentName = "John", Age = 18 } };
                  List<TestClass> TestList2 = new List<TestClass>() { new TestClass() { StudentID = 1, StudentName = "John", Age = 18 } };
                  var result = TestList1.SequenceEqual(TestList2); // false
              自定义引用类型比较
                  如果不想比较引用类型的时候比较引用地址,那么可以使用自定义比较
                  首先,创建一个实现了IEqualityComparer接口的类
                      private class SequenceEqualComparer : IEqualityComparer<TestClass>
                      {
                          public bool Equals(TestClass x, TestClass y)
                          {
                              if(x.StudentID == y.StudentID && x.StudentName == y.StudentName && x.Age == y.Age)
                              {
                                  return true;
                              }
                              return false;
                          }
                          public int GetHashCode(TestClass obj)
                          {
                              return obj.GetHashCode();
                          }
                      }
                  使用
                      List<TestClass> TestList1 = new List<TestClass>() { new TestClass() { StudentID = 1, StudentName = "John", Age = 18 } };
                      List<TestClass> TestList2 = new List<TestClass>() { new TestClass() { StudentID = 1, StudentName = "John", Age = 18 } };
                      var result = TestList1.SequenceEqual(TestList2, new SequenceEqualComparer()); // true
      ** 串联运算符
          > Concat运算符
              用于连接两个集合
              var result = TestList1.Concat(TestList2);
      ** 生成运算符
          > DefaultIfEmpty操作符
              如果调用此方法的集合是空的则返回一个新的集合,新集合包含一个默认值元素
              不指定默认值
                  List<string> list = new List<string>();
                  var result = list.DefaultIfEmpty(); // 结果 [null]
              指定默认值
                  var result = list.DefaultIfEmpty("haha"); // 结果 ["haha"]
              本质
                  DefaultIfEmpty本质作用是将一个集合拷贝了一份,如果集合是空的自动填充一个默认值
                  List<string> list = new List<string>() { "a" };
                  var temp = list.DefaultIfEmpty("haha");
                  var result = temp == list; // false
          > Empty, Range, Repeat 操作符
              这三个运算符不是IEnumerable 和 IQueryable的扩展方法,而是Enumerable的静态方法
              Empty操作符
                  返回一个空的集合
                  var result = (Enumerable.Empty<string>()).GetType().Name; // "String[]"
              Range操作符
                  返回一个集合,元素从指定的数字开始,按照指定的个数依次递增
                  var result = Enumerable.Range(10, 10); // [10,11,12,13,14,15,16,17,18,19]
              Repeat操作符
                  返回一个集合,元素是指定个数的相同的指定元素
                  var result = Enumerable.Repeat<string>("a", 10); // ["a","a","a","a","a","a","a","a","a","a"]
      ** 集操作符
          > Distinct
              取出集合中重复项,并返回一个新的集合
              对值类型集合的操作
                  List<string> list = new List<string>() { "a", "b", "c", "d", "b", "c" };
                  var result = list.Distinct(); // ["a","b","c","d"]
              对引用类型集合的操作,默认无效,需要自己实现IEqualityComparer类
                  首先实现IEqualityComparer类
                      Equals,GetHashCode方法会自动调用,当GetHashCode返回的整数(引用)不一致,那么会执行Equals方法
                      private class DistinctComparer : IEqualityComparer<TestClass>
                      {
                          public bool Equals(TestClass x, TestClass y)
                          {
                              if(x.StudentID == y.StudentID && x.StudentName == y.StudentName && x.Age == y.Age)
                              {
                                  return true;
                              }
                              return false;
                          }
                          public int GetHashCode(TestClass obj)
                          {
                              return obj.StudentID.GetHashCode(); // 注意,表示如果 StudentID的GetHashCode 相同,那么过滤掉这个数据
                          }
                      }
                  使用
                      List<TestClass> studentList = new List<TestClass>() {
                          new TestClass() { StudentID = 1, StudentName = "John", Age = 18 } ,
                          new TestClass() { StudentID = 1, StudentName = "John", Age = 18 } ,
                          new TestClass() { StudentID = 2, StudentName = "Steve",  Age = 15 } 
                      };
                      var result = studentList.Distinct(new DistinctComparer());
          > Except
              返回一个新的集合,集合的成员是list1在list2中不存在的元素
              对值类型集合的操作
                  List<string> list1 = new List<string>() { "a", "b", "c" };
                  List<string> list2 = new List<string>() { "c", "d", "a" };
                  var result = list1.Except(list2); // ["b"]
              对引用类型集合的操作,同样也要自己实现IEqualityComparer类
                  创建一个IEqualityComparer类,和上面一模一样
                      private class ExceptComparer : IEqualityComparer<TestClass>
                      {
                          public bool Equals(TestClass x, TestClass y)
                          {
                              if (x.StudentID == y.StudentID && x.StudentName == y.StudentName && x.Age == y.Age)
                              {
                                  return true;
                              }
                              return false;
                          }
                          public int GetHashCode(TestClass obj)
                          {
                              return obj.StudentID.GetHashCode(); // 注意,表示如果 StudentID的GetHashCode 相同,那么过滤掉这个数据
                          }
                      }
                  使用
                      List<TestClass> studentList1 = new List<TestClass>() {
                          new TestClass() { StudentID = 1, StudentName = "John", Age = 18 } ,
                          new TestClass() { StudentID = 1, StudentName = "John", Age = 18 } ,
                          new TestClass() { StudentID = 2, StudentName = "Steve",  Age = 15 }
                      };
                      List<TestClass> studentList2 = new List<TestClass>() {
                          new TestClass() { StudentID = 1, StudentName = "John", Age = 18 } ,
                          new TestClass() { StudentID = 3, StudentName = "John", Age = 18 } ,
                          new TestClass() { StudentID = 4, StudentName = "Steve",  Age = 15 }
                      };
                      var result = studentList1.Except(studentList2, new ExceptComparer()); // [{"StudentID":2,"StudentName":"Steve","Age":15}]
          > Intersect
              相当于取交集
              值类型集合操作
                  List<string> list1 = new List<string>() { "a", "b", "c" };
                  List<string> list2 = new List<string>() { "c", "d", "a" };
                  var result = list1.Intersect(list2); // ["a","c"]
              引用类型集合操作,同样也是要创建IEqualityComparer类,实现和上面是一模一样,不再赘述
              使用
                  var result = studentList1.Intersect(studentList2, new IntersectComparer());
                  // 返回结果 [{"StudentID":1,"StudentName":"John","Age":18}]
          > Union
              将两个集合拼接起来,并且剔除掉重复项
              值类型集合操作
                  List<string> list1 = new List<string>() { "a", "b", "c", "a", "b" };
                  List<string> list2 = new List<string>() { "c", "d", "a" };
                  var result = list1.Union(list2); // ["a","b","c","d"]
              引用类型集合操作,同样也是要创建IEqualityComparer类,实现和上面是一模一样,不再赘述
              使用
                  var result = studentList1.Union(studentList2, new UnionComparer());
                  返回结果如下
                  /*
                      [
                          {"StudentID":1,"StudentName":"John","Age":18},
                          {"StudentID":2,"StudentName":"Steve","Age":15},
                          {"StudentID":3,"StudentName":"John","Age":18},
                          {"StudentID":4,"StudentName":"Steve","Age":15}
                      ]
                  */
      ** 分区操作符
          > Skip操作符
              过滤掉集合中指定个数的元素,返回剩余元素组成的集合
              List<string> list = new List<string>() { "a", "b", "c" };
              var result = list.Skip(2); // ["c"]
          > SkipWhile操作符
              指定条件过滤,如果条件满足全部过滤掉,直到条件为false,返回剩余元素组成的集合
              List<int> list = new List<int>() { 1, 2, 5, 2, 4, 5, 6 };
              var result = list.SkipWhile((s, i) => s < 3); // [5,2,4,5,6]
          > Take操作符
              功能和Skip相反,获取指定数量的元素,并返回新的集合
              List<string> list = new List<string>() { "a", "b", "c" };
              var result = list.Take(2); // ["a","b"]
          > TakeWhile操作符
              功能和SkipWhile相反,获取满足指定条件的元素,直到条件不满足,返回新的集合
              List<int> list = new List<int>() { 1, 2, 5, 2, 4, 5, 6 };
              var result = list.TakeWhile((s, i) => s < 3); // [1,2]
      ** 转换运算符
          > AsEnumerable操作符
              将集合强制转换成IEnumerable集合
              int[] arr = new int[] { 1, 2, 3, 4, 5 };
              var result = arr.AsEnumerable();
          > AsQueryable操作符
              将集合强制转换成IQueryable集合
              List<int> list = new List<int>() { 1, 2, 5, 2, 4, 5, 6 };
              var result = list.AsQueryable();
          > Cast操作符
              作用和AsEnumerable是一样的
              int[] arr = new int[] { 1, 2, 3, 4, 5 };
              var result = arr.Cast<int>(); 等效于 var result = (IEnumerable<int>)arr;
          > ToArray,ToList,ToDictionary扩展方法
              To系列的操作,会强制让sql语句执行结果并且将数据缓存在本地
              int[] arr = new int[] { 1, 2, 3, 4, 5 };
              ToArray使用
                  int[] result = arr.ToArray<int>();
              ToList使用
                  List<int> result = arr.ToList<int>();
              ToDictionary使用
                  var result = arr.ToDictionary<int, int>(s => s);
      
    3. Linq中的Expression类型

      由Func和Action类型的委托构建的lambada表达式在编译期间会转换成可执行的代码,linq引入新的Expression类型,将lambda表达式转换成Expression树而不是可执行代码
      传统写代理的方式
          Func<int, bool> isTest = s => s > 5;
      Expression写代理的方式
          Expression<Func<int, bool>> isTest = s => s > 5;
      调用Expression代理
          调用之前需要先编译一下
          Func<int, bool> isIWant = isTest.Compile();
          bool result = isIWant(3);
      为什么要有表达式树?
          编译的区别
              Func编译后的代码 {Method = {Boolean <.ctor>b__9_0(Int32)}}
              Expression编译后的代码 {s => (s > 5)}
              很明显的感觉到,Func编译后被改了,表达式树更加的透明,你可以轻松的调用Expression的方法访问方法的每一个部分
          处理代码的区别
              Func值适合当前程序集中运行,也就是说只适合内存中的集合,因为如果涉及数据库查询的话,数据库无法获知编译后的IL代码到底是个啥
              Expression表达式树,专门用来处理类似数据库的操作
          执行效率
              Func要想操作数据库,需要借助Entity Frameworks将可执行代码编译成Sql查询字符串发送到sql server数据库中
              使用Expression表达式树,可以轻松的将lambda表达式转换成Sql语句,因为Expression内置了很多属性和方法方便获取表达式的每一部分,所以执行效率更快
          总之,一句话,操作数据库使用Expression更好
      
    4. 延迟执行linq查询

      linq表达式不会立即执行,而是用到了才会调用,从而保证每次使用linq时都是最新的数据
      默认情况下linq的延迟加载不会有什么特殊的效果,只是简单的延迟而已,但是你可以自定义扩展方法使用yield关键字实现自己的延迟效果
      首先,要定义扩展方法,需要一个顶级静态类
          public static class EnumerableExtensionMethodsDemo
          {
              public static IEnumerable<int> GetIWant(this List<int> test)
              {
                  foreach (int item in test)
                  {
                      if(item > 5 && item < 10)
                      {
                          yield return item;
                      }
                  }
              }
          }
      使用
          List<int> list = new List<int>() { 1, 2, 10, 50, 30, 5, 7, 9, 11 };
          var result = from s in list.GetIWant() select s;
          foreach (int i in result) 
          {
              // 在这里才会调用result查询语句
          }
      
    5. 立即执行linq查询

      上面讲到的以to开头的扩展方法,都可以让linq语句立即执行
      
    6. linq中使用let关键字

      List<string> list = new List<string>() { "sa", "rb", "bc", "sd" };
      var result = from s in list where s.ToLower().StartsWith("s") select s.ToLower();
      上面这个查询语句中 ToLower 使用了两次,很啰嗦,可以使用let简化
      var result = from s in list
                   let lowerItem = s.ToLower()
                   where lowerItem.StartsWith("s")
                   select lowerItem;
      
    7. into关键字

      into关键字单独使用的作用,是将上个查询语句的结果传递到下一个查询语句中,两个查询语句中的变量互不影响
      List<string> list = new List<string>() { "sa", "rb", "bc", "sd" };
      var result = from s in list
                   where s.ToLower().StartsWith("s")
                   select s
                   into s
                   where s.ToLower().EndsWith("a")
                   select s; // ["sa"]
      
  • 相关阅读:
    django orm中filter(条件1).filter(条件2)与filter(条件1,条件2)的区别 哈欠涟涟的日志 网易博客
    提示:ERROR 1044 (42000): Access denied for user
    取消选中的区域
    1.XML复习、HTML DOM 复习 2.simpleXML方式解析XML 3.XPath 4,MVC
    JSP的内置对象(session)
    每月自评之三:2013年3月
    HDU1405:The Last Practice
    一种Playfair密码变种加密方法如下:首先选择一个密钥单词(称为pair)(字母不重复,且都为小写字母),然后与字母表中其他字母一起填入至一个5x5的方阵中,填入方法如下:
    一个经典实用的 IPtables Shell 脚本
    static class 静态类
  • 原文地址:https://www.cnblogs.com/ye-hcj/p/8098006.html
Copyright © 2011-2022 走看看