本文介绍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"]

c# linq查询语句详细使用介绍的更多相关文章

  1. 简单的Linq查询语句

    下面我来我大家介绍几种简单的查询方式. 1.简单语法 这个LINQ语句的第一个关键字是from,from后面加的是范围变量,范围变量后加in,后加上事先实例化的模型,然后点出数据的来源. List是列 ...

  2. linq查询语句转mongodb

    && (与操作) 子表达式可以通过&&合并来查询满足所有子表达式的文档 var query = from c in collection.AsQueryable< ...

  3. C#高级知识点概要(3) - 特性、自动属性、对象集合初始化器、扩展方法、Lambda表达式和Linq查询

    1.特性(Attributes) 特性(Attributes),MSDN的定义是:公共语言运行时允许你添加类似关键字的描述声明,叫做attributes, 它对程序中的元素进行标注,如类型.字段.方法 ...

  4. C# LINQ查询表达式用法对应Lambda表达式

    C#编程语言非常优美,我个人还是非常赞同的.特别是在学习一段时间C#后发现确实在它的语法和美观度来说确实要比其它编程语言强一些(也可能是由于VS编译器的加持)用起来非常舒服,而且对于C#我觉得他最优美 ...

  5. 【总结】LINQ查询基本操作列表

    每个LINQ查询都以from子句开始,from子句包括以下两个功能. 指定查询将采用数据源. 定义一个本地变量,表示数据源中单个元素. string[] values = { "中国&quo ...

  6. LINQ中的一些查询语句格式

    LINQ的基本格式如下所示:var <变量> = from <项目> in <数据源> where <表达式> orderby <表达式> ...

  7. 浅谈sql 、linq、lambda 查询语句的区别

    浅谈sql .linq.lambda 查询语句的区别 LINQ的书写格式如下: from 临时变量 in 集合对象或数据库对象 where 条件表达式 [order by条件] select 临时变量 ...

  8. ES 常用的查询语句介绍

    elasticsearch定义了两种查询方式: 一.索引(index).type.document 相关语句 1.列出所有索引的状态 GET /_cat/indices?v health status ...

  9. 这里我们介绍的是 40+ 个非常有用的 Oracle 查询语句,主要涵盖了日期操作,获取服务器信息,获取执行状态,计算数据库大小等等方面的查询。这些是所有 Oracle 开发者都必备的技能,所以快快收藏吧!

    日期/时间 相关查询 获取当前月份的第一天 运行这个命令能快速返回当前月份的第一天.你可以用任何的日期值替换 “SYSDATE”来指定查询的日期. SELECT TRUNC (SYSDATE, 'MO ...

随机推荐

  1. springcloud一些概念知识

    1.Eureka 1)Eureka服务治理体系支持跨平台 2)三个核心概念:服务注册中心.服务提供者以及服务消费者 3)服务续约:注册完服务之后,服务提供者会维护一个心跳来不停的告诉Eureka Se ...

  2. SpringCloud-路由网关(Zuul)

    在微服务架构中,需要几个基础的服务治理组件,包括服务注册与发现.服务消费.负载均衡.断路器.只能路由.配置管理等,由这几个基础组件相互协作,共同组建了一个简单的微服务系统. 在Spring Cloud ...

  3. 介绍一下Hibernate的二级缓存

    介绍一下Hibernate的二级缓存 按照以下思路来回答:(1)首先说清楚什么是缓存,(2)再说有了hibernate的Session就是一级缓存,即有了一级缓存,为什么还要有二级缓存,(3)最后再说 ...

  4. pf_ring DNA接收流程代码分析

    经过一个月的学习,对pf_ring DNA的内核部分有了一些认识,本文侧重pf_ring对ixgbe的改动分析. 先说一说接收流程吧,流程如下: 其中,硬中断处理函数是ixgbe_msix_clean ...

  5. HTML中table边框的显示总结

    一.1.显示表格的4个边框:<table border frame=box>2.只显示上边框: <table border frame=above>3.只显示下边框: < ...

  6. Elasticsearch Suggester 学习

    suggester搜索就像百度搜索框中的提示类似. Elasticsearch 中提供类似的搜索功能. 答案就在Suggesters API. Suggesters基本的运作原理是将输入的文本分解为t ...

  7. review35

    使用Thread创建线程通常使用的方法是:Thread(Runnable target).该构造方法中的参数是一个Runnable类型的接口,因此在创建线程对象时必须向构造方法的参数传递一个实现Run ...

  8. python中的excel操作

    一. Excel在python中的应用 存测试数据 有的时候大批量的数据,我们需要存到数据库中,在测试的时候才能用到.测试的时候就从数据库中读取出来.这点是非常重要的! 存测试结果 二. Excel中 ...

  9. AI探索(四)NumPy库的使用

    NumPy(Numerical Python) 是 Python 语言的一个扩展程序库,支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库. umPy 是一个运行速度非常快的数学库, ...

  10. eclipse部署和启动guns

    eclipse部署guns: 1.import -> 搜索maven -> Existing Maven Projects -> 选择guns根目录 2.修改配置文件: spring ...