• 从LINQ开始之LINQ to Objects(上)


    LINQ概述

    LINQ,语言集成查询(Language Integrated Query),它允许使用C#或VB代码以查询数据库相同的方式来操作不同的数据源。

    1.LINQ体系结构

    从上图可以看出,LINQ总共包括五个部分:LINQ to Objects、LINQ to DataSets、LINQ to SQL、LINQ to Entities、LINQ to XML。

    LINQ to Objects:对内存中集合的操作

    LINQ to DataSets:对数据集Datatable的操作

    LINQ to SQL:对SQL Server数据源的操作,微软把开发的重点从LINQ to SQL转移到了LINQ to Entities并且宣布LINQ to SQL不再提供更新

    LINQ to Entities:是 Entity Framework的一部分并且取代LINQ to SQL作为在数据库上使用 LINQ的标准机制

    LINQ to XML:对XML数据源的操作

    2.LINQ的语法

    下面是一个简单的示例,查询一个int数组中小于5的元素,并按照从小到大的顺序排列:

    int[] arr = new int[] { 1, 4, 2, 6, 7, 9, 5, 1, 2, 4 };
            var query = from r in arr
                        where r < 5
                        orderby r
                        select r;
            foreach (var item in query)
            {
                Console.WriteLine(item);
            }
            Console.ReadLine();

    由此示例可以看出:LINQ查询表达式以from子句开头,以select子句结束。在两个子句之间,可以使用where、orderby等查询操作符。

    LINQ有两种语法:Lambda语法和Query语法,编译器会在程序编译时转换LINQ查询,以调用相应的扩展方法。

    以下是LINQ表达式结构示意图:

    引用自百度百科

    LINQ to Objects

    LINQ to Objects中的扩展方法在System.Core程序集的System.Linq命名空间中定义。

    1.Enumerable类定义的标准查询操作符:

    下面介绍使用这些操作符的示例:

    首先,我们需要创建基本的实体类Employee:

    /// <summary>
    /// 员工类
    /// </summary>
    public class Employee
    {
        //员工编号
        public string EmployeeId { get; private set; }
        //员工姓名
        public string EmployeeName { get; private set; }
        //年龄
        public int Age { get; private set; }
        //入职日期
        public DateTime EntryDate { get; private set; }
        //性别
        public string Sex { get; private set; }
        //部门
        public string Department { get; private set; }
        //薪水
        public int Salary { get; private set; }
        //爱好
        public IEnumerable<string> Hobby { get; private set; }
    
         public Employee(string employeeId, string employeeName, int age, DateTime entryDate, Sex sex, Department department, int salary, IEnumerable<string> hobby)
        {
            this.EmployeeId = employeeId;
            this.EmployeeName = employeeName;
            this.Age = age;
            this.EntryDate = entryDate;
            this.Sex = sex.ToString();
            this.Department = department.ToString();
            this.Salary = salary;
            this.Hobby = hobby;
        }
    }
    
    //性别
    public enum Sex
    {
        Male,
        Female
    }
    
    //部门
    public enum Department
    {
        HR,
        IT,
        PD,
        FD,
        QC,
        MD
    }

    然后,创建列表employees保存10名员工的基本信息:

    List<Employee> employees = new List<Employee>()
            {
                new Employee("001","Mike",32,new DateTime(2016,2,20),Sex.Male,Department.IT,200000,new string[] { "swimming","shopping"}),
                new Employee("002","Jack",38,new DateTime(2007,5,12),Sex.Male,Department.HR,409989,new string[] { "reading"}),
                new Employee("003","Adolph",25,new DateTime(2017,3,23),Sex.Male,Department.IT,100000,new string[] { "play computer games","watch TV","listen to music"}),
                new Employee("004","Antony",30,new DateTime(2010,11,20),Sex.Male,Department.FD,320000, new string[] { "play chess","run"}),
                new Employee("005","Asa",28,new DateTime(2014,10,10),Sex.Female,Department.FD,120000,new string[] { "shopping"}),
                new Employee("006","Bernie",31,new DateTime(2008,4,5),Sex.Male,Department.PD,220000,new string[] { "play basketball"}),
                new Employee("007","Carl",26,new DateTime(2015,1,30),Sex.Male,Department.QC,100000,new string[] { "play chess","go fishing"}),
                new Employee("008","Duncan",30,new DateTime(2009,6,9),Sex.Male,Department.MD,250000,new string[] { "play computer games"}),
                new Employee("009","Aimee",24,new DateTime(2017,1,20),Sex.Female,Department.HR,80000,new string[] { "reading","run"}),
                new Employee("010","Cassie",31,new DateTime(2014,3,3),Sex.Female,Department.IT,350000,new string[] { "watch TV" })
            };

    1)筛选操作符(Where、OfType<TResult>)

    Where:根据表达式函数过滤元素

    //查询年龄大于30岁,IT或HR部门所有员工的编号及姓名
            var filter = from r in employees
                        where r.Age > 30 && (r.Department == Department.IT.ToString() || r.Department == Department.HR.ToString())
                        select r;
    
            foreach (var item in filter)
            {
                Console.WriteLine("EmployId: " +item.EmployeeId + " EmployeeName: " + item.EmployeeName);
            }
    
            //******************************Output*******************************
            //EmployId: 001 EmployeeName: Mike
            //EmployId: 002 EmployeeName: Jack
            //EmployId: 010 EmployeeName: Cassie
            //*******************************************************************

    OfType<TResult>:类型筛选

    //筛选出指定数组中所有int类型的元素
            object[] data = { "One", 2, 3, "Four", "Five", 6 };
            var typeFilter = data.OfType<int>();
            foreach (var item in typeFilter)
            {
                Console.WriteLine(item);
            }
    
            //******************************Output*******************************
            //2
            //3
            //6
            //*******************************************************************

    2)投射操作符(Select、SelectMany)

    Select:根据选择器函数选择的结果值投射到新的类型元素上

    SelectMany:C#编译器把复合的from子句和LINQ查询转换为SelectMany扩展方法,用于迭代序列的序列。

    //查找个人爱好中有reading的员工的姓名
            var doubleFrom = from r in employees
                             from h in r.Hobby
                             where h == "reading"
                             select r.EmployeeName;
            foreach (var item in doubleFrom)
            {
                Console.WriteLine(item);
            }
    
            //******************************Output*******************************
            //Jack
            //Aimee
            //*******************************************************************
    
            //--------------------------强势分隔符--------------------------------
    
            //使用SelectMany扩展方法返回个人爱好中有reading的员工的姓名
            var selectMany = employees.
                SelectMany(r => r.Hobby,
                (r, h) => new { Employee = r, Hobby = h }).
                Where(r => r.Hobby == "reading").
                Select(r => r.Employee.EmployeeName);
            foreach (var item in selectMany)
            {
                Console.WriteLine(item);
            }
            //******************************Output*******************************
            //Jack
            //Aimee
            //*******************************************************************

    3)排序操作符(OrderBy、ThenBy、OrderByDescending、ThenByDescending、Reverse)

    OrderBy、OrderByDescending:升序排序、降序排序

    ThenBy、ThenByDescending:如果第一次排序有元素相同,进行第二次排序(使用LINQ查询时只需把需要排序的关键字用逗号隔开)

    //按照年龄从大到小排序,如果年龄相同,则按照员工编号正向排序,输出员工的编号、姓名、年龄,
            var orderBy = from o in employees
                          orderby o.Age descending, o.EmployeeId
                          select o;
            foreach (var item in orderBy)
            {
                Console.WriteLine("EmployeeId: " + item.EmployeeId + " EmployeeName:" + item.EmployeeName + " Age:" + item.Age);
            }
    
            //******************************Output*******************************
            //EmployeeId: 002 EmployeeName: Jack Age:38
            //EmployeeId: 001 EmployeeName: Mike Age:32
            //EmployeeId: 006 EmployeeName: Bernie Age:31
            //EmployeeId: 010 EmployeeName: Cassie Age:31
            //EmployeeId: 004 EmployeeName: Antony Age:30
            //EmployeeId: 008 EmployeeName: Duncan Age:30
            //EmployeeId: 005 EmployeeName: Asa Age:28
            //EmployeeId: 007 EmployeeName: Carl Age:26
            //EmployeeId: 003 EmployeeName: Adolph Age:25
            //EmployeeId: 009 EmployeeName: Aimee Age:24
            //*******************************************************************
            //--------------------------强势分隔符--------------------------------
            //使用ThenBy扩展方法实现年龄相同,按员工编号正向排序
            var thenBy = employees
                         .OrderByDescending(t => t.Age)
                         .ThenBy(t => t.EmployeeId)
                         .Select(t => "EmployeeId: " + t.EmployeeId + " EmployeeName:" + t.EmployeeName + " Age:" + t.Age);
            foreach (var item in thenBy)
            {
                Console.WriteLine(item);
            }
    
            //******************************Output*******************************
            //EmployeeId: 002 EmployeeName: Jack Age:38
            //EmployeeId: 001 EmployeeName: Mike Age:32
            //EmployeeId: 006 EmployeeName: Bernie Age:31
            //EmployeeId: 010 EmployeeName: Cassie Age:31
            //EmployeeId: 004 EmployeeName: Antony Age:30
            //EmployeeId: 008 EmployeeName: Duncan Age:30
            //EmployeeId: 005 EmployeeName: Asa Age:28
            //EmployeeId: 007 EmployeeName: Carl Age:26
            //EmployeeId: 003 EmployeeName: Adolph Age:25
            //EmployeeId: 009 EmployeeName: Aimee Age:24
            //*******************************************************************

    Revise:使用扩展方法反转集合中的元素顺序

    //按照年龄从大到小排序后再反转元素的顺序
            var reverse = employees
                .OrderByDescending(r => r.Age)
                .Reverse()
                .Select(r => "EmployeeId: " + r.EmployeeId + " EmployeeName:" + r.EmployeeName + " Age:" + r.Age);
            foreach (var item in reverse)
            {
                Console.WriteLine(item);
            }
    
            //******************************Output*******************************
            //EmployeeId: 009 EmployeeName: Aimee Age:24
            //EmployeeId: 003 EmployeeName: Adolph Age:25
            //EmployeeId: 007 EmployeeName: Carl Age:26
            //EmployeeId: 005 EmployeeName: Asa Age:28
            //EmployeeId: 008 EmployeeName: Duncan Age:30
            //EmployeeId: 004 EmployeeName: Antony Age:30
            //EmployeeId: 010 EmployeeName: Cassie Age:31
            //EmployeeId: 006 EmployeeName: Bernie Age:31
            //EmployeeId: 001 EmployeeName: Mike Age:32
            //EmployeeId: 002 EmployeeName: Jack Age:38
            //*******************************************************************

    4)连接操作符(Join、GroupJoin)

    为了完成这部分的示例,我们需要准备新的实体类和列表

    /// <summary>
    /// 部门信息
    /// </summary>
    public class DepartmentInfo
    {
        //部门编号
        public string DepartmentId { get; private set; }
        //部门名称
        public string DepartmentName { get; private set; }
        //部门总监
        public string Director { get; private set; }
    
        public DepartmentInfo(string departmentId, string departmentName, string director)
        {
            this.DepartmentId = departmentId;
            this.DepartmentName = departmentName;
            this.Director = director;
        }
    }
    
    /// <summary>
    /// 杰出团队
    /// </summary>
    public class OutstandingTeam
    {
        public int Year { get; private set; }
        public string Department { get; private set; }
    
        public OutstandingTeam(int year, string department)
        {
            this.Year = year;
            this.Department = department;
        }
    }

    创建列表departmentInfo保存各部门的信息

    List<DepartmentInfo> deparmentInfo = new List<DepartmentInfo>()
            {
                new DepartmentInfo("001","HR","Oliver"),
                new DepartmentInfo("002","IT","Oscar"),
                new DepartmentInfo("003","PD","ELLA"),
                new DepartmentInfo("004","FD","Alice"),
                new DepartmentInfo("005","QC","Kai")
            };

    创建列表outstandingTeams保存2010年起获得杰出团队的部门

    List<OutstandingTeam> outstandingTeams = new List<OutstandingTeam>()
            {
                new OutstandingTeam(2010,"IT"),
                new OutstandingTeam(2011,"FD"),
                new OutstandingTeam(2012,"HR"),
                new OutstandingTeam(2013,"IT"),
                new OutstandingTeam(2014,"QC"),
                new OutstandingTeam(2015,"HR"),
                new OutstandingTeam(2016,"HR"),
                new OutstandingTeam(2017,"MD")
            };

    Join:根据特定的条件合并两个数据源

    //查询员工的姓名,部门以及该部门的总监
            var join = from j in employees
                       join d in deparmentInfo
                       on j.Department equals d.DepartmentName
                       select new
                       {
                           j.EmployeeName,
                           j.Department,
                           d.Director
                       };
            foreach (var item in join)
            {
                Console.WriteLine("EmployeeName: " + item.EmployeeName + " Department:" + item.Department + " Director:" + item.Director);
            }
    
            //******************************Output*******************************
            //EmployeeName: Mike Department:IT Director:Oscar
            //EmployeeName: Jack Department:HR Director:Oliver
            //EmployeeName: Adolph Department:IT Director:Oscar
            //EmployeeName: Antony Department:FD Director:Alice
            //EmployeeName: Asa Department:FD Director:Alice
            //EmployeeName: Bernie Department:PD Director:ELLA
            //EmployeeName: Carl Department:QC Director:Kai
            //EmployeeName: Aimee Department:HR Director:Oliver
            //EmployeeName: Cassie Department:IT Director:Oscar
            //*******************************************************************

    这时候我们会发现,输出的内容里面少了员工Duncan的信息,检查后发现,原来deparmentInfo没有添加MD部门的相关信息,此时希望查询所有员工,若匹配不到该部门信息,Director返回N/A。

    //查询员工的姓名,部门以及该部门的总监,若匹配不到该部门信息,Director返回N/A
            var leftjoin = from j in employees
                           join d in deparmentInfo
                           on j.Department equals d.DepartmentName into jd
                           from d in jd.DefaultIfEmpty()
                           select new
                           {
                               j.EmployeeName,
                               j.Department,
                               Director = d == null ? "N/A" : d.Director
                           };
            foreach (var item in leftjoin)
            {
                Console.WriteLine("EmployeeName: " + item.EmployeeName + " Department:" + item.Department + " Director:" + item.Director);
            }
    
            //******************************Output*******************************
            //EmployeeName: Mike Department:IT Director:Oscar
            //EmployeeName: Jack Department:HR Director:Oliver
            //EmployeeName: Adolph Department:IT Director:Oscar
            //EmployeeName: Antony Department:FD Director:Alice
            //EmployeeName: Asa Department:FD Director:Alice
            //EmployeeName: Bernie Department:PD Director:ELLA
            //EmployeeName: Carl Department:QC Director:Kai
            //EmployeeName: Duncan Department:MD Director:N/A
            //EmployeeName: Aimee Department:HR Director:Oliver
            //EmployeeName: Cassie Department:IT Director:Oscar
            //*******************************************************************

    GroupJoin:基于键相等对两个序列的元素进行关联并对结果进行分组。

    //查找每个部门获得杰出团队的年份
            var groupJoin = from d in deparmentInfo
                            join o in outstandingTeams on d.DepartmentName equals o.Department into g
                            select new
                            {
                                DepartmentName = d.DepartmentName,
                                Years = g 
                            };
            foreach (var item in groupJoin)
            {
                Console.WriteLine("Department:" + item.DepartmentName);
    
                if (item.Years.Count() == 0)
                {
                    Console.WriteLine("Never won the award");
                }
                foreach (var champions in item.Years)
                {
                    Console.WriteLine(champions.Year);
                }
    
            }
    
            //******************************Output*******************************
            //Department: HR
            //2012
            //2015
            //2016
            //Department: IT
            //2010
            //2013
            //Department: PD
            // Never won the award
            // Department:FD
            //2011
            //Department: QC
            //2014
            //*******************************************************************

    5)组合操作符(GroupBy、ToLookup)

    GroupBy:根据关键字值对查询结果进行分组。

    //查询每个部门及人数
            var groupBy = from e in employees
                          group e by e.Department into g
                          select new
                          {
                              g.Key,
                              Count = g.Count()
                          };
            foreach (var item in groupBy)
            {
                Console.WriteLine("Department: " + item.Key + " Count: " + item.Count);
            }
            //******************************Output*******************************
            //Department: IT Count: 3
            //Department: HR Count: 2
            //Department: FD Count: 2
            //Department: PD Count: 1
            //Department: QC Count: 1
            //Department: MD Count: 1
            //*******************************************************************

    ToLookup:通过创建一对多的字典来组合元素

    //使用ToLookup实现爱好阅读的员工姓名
            var toLookup = (from e in employees
                            from h in e.Hobby
                            select new
                            {
                                Hobby = h,
                                Name = e.EmployeeName
                            }).ToLookup(he => he.Hobby, he => he.Name);
    
            if (toLookup.Contains("reading"))
            {
                foreach (var item in toLookup["reading"])
                {
                    Console.WriteLine(item);
                }
            }
    
            //******************************Output*******************************
            //Jack
            //Aimee
            //*******************************************************************

    6)限定操作符(Any、All、Contains)

    Any:是否包含满足条件的元素

    //是否有小于20岁的员工
            bool any = employees.Any(r => r.Age < 20);
            Console.WriteLine(any);
    
            //******************************Output*******************************
            //False
            //*******************************************************************

    ALL:是否所有元素都满足条件

    //是否所有员工都大于20岁
            bool all = employees.All(r => r.Age > 20);
            Console.WriteLine(all);
    
            //******************************Output*******************************
            //True
            //*******************************************************************

    Contains:检索某个元素是否在集合中

    //员工列表中是否包含david
            Employee david = new Employee("011", "David", 28, new DateTime(2017, 5, 21), Sex.Male, Department.IT, 100000, new string[] { "run" });
            employees.Add(david);
            bool contains = employees.Contains(david);
            Console.WriteLine(contains);
    
            //******************************Output*******************************
            //True
            //*******************************************************************

    7)分区操作符(Take、Skip、TakeWhile、SkipWhile)

    Take:从集合中提取指定数量的元素

    Skip:跳过集合中指定数量的元素

    //忽略薪水最高的5位,查询剩余部分薪水最高的员工姓名及薪水
            var skip = (from e in employees
                        orderby e.Salary descending
                        select e).Skip(5).Take(1);
            foreach (var item in skip)
            {
                Console.WriteLine("EmployeeName: " + item.EmployeeName + " Salary: " + item.Salary);
            }
    
            //******************************Output*******************************
            //EmployeeName: Mike Salary: 200000
            //*******************************************************************

    TakeWhile:提取条件为真时的元素

    //取集合中满足条件salary大于1000000之前的所有员工的姓名和薪水
            var takeWhile = (from e in employees
                             select e).TakeWhile(r => r.Salary > 100000);
            foreach (var item in takeWhile)
            {
                Console.WriteLine("EmployeeName: " + item.EmployeeName + " Salary: " + item.Salary);
            }
    
            //******************************Output*******************************
            //EmployeeName: Mike Salary: 200000
            //EmployeeName: Jack Salary: 409989
            //*******************************************************************

    SkipWhere:跳过集合中满足条件的元素,当条件不成立时返回剩余的所有元素

    //跳过集合中满足条件salary大于100000的元素,当条件不成立时返回剩余的所有元素
            var skipWhile = (from e in employees
                             select e).SkipWhile(r => r.Salary > 100000);
            foreach (var item in skipWhile)
            {
                Console.WriteLine("EmployeeName: " + item.EmployeeName + " Salary: " + item.Salary);
            }
    
            //******************************Output*******************************
            //EmployeeName: Adolph Salary: 100000
            //EmployeeName: Antony Salary: 320000
            //EmployeeName: Asa Salary: 120000
            //EmployeeName: Bernie Salary: 220000
            //EmployeeName: Carl Salary: 100000
            //EmployeeName: Duncan Salary: 250000
            //EmployeeName: Aimee Salary: 80000
            //EmployeeName: Cassie Salary: 350000
            //*******************************************************************

    8)Set操作符(Distinct、Union、Intersect、Except、Zip)

    Distinct:从集合中删掉重复的元素

    //给所有员工的薪水排序,去掉重复的
            var distinct = (from e in employees
                            orderby e.Salary 
                            select e.Salary).Distinct();
    
            foreach (var item in distinct)
            {
                Console.WriteLine(item);
            }
    
            //******************************Output*******************************
            //80000
            //100000
            //120000
            //200000
            //220000
            //250000
            //320000
            //350000
            //409989
            //*******************************************************************

    Union、Intersect、Except:并集、交集、差集

    首先,我们准备两个集合:员工姓名以A开头和员工姓名以E结尾

    var startWithA = (from e in employees
                              where e.EmployeeName.StartsWith("A")
                              select e).ToList();
    
            var endWithE = (from e in employees
                            where e.EmployeeName.ToUpper().EndsWith("E")
                            select e).ToList();

    以下分别取两个集合的并集、交集、差集:

    //查询两个集合的并集
            var union = startWithA.Union(endWithE);
            foreach (var item in union)
            {
                Console.WriteLine(item.EmployeeName);
            }
    
            //******************************Output*******************************
            //Adolph
            //Antony
            //Asa
            //Aimee
            //Mike
            //Bernie
            //Cassie
            //*******************************************************************
    
            //--------------------------强势分隔符--------------------------------
    
            //查询两个集合的交集
            var intersect = startWithA.Intersect(endWithE);
            foreach (var item in intersect)
            {
                Console.WriteLine(item.EmployeeName);
            }
    
            //******************************Output*******************************
            //Aimee
            //*******************************************************************
    
            //--------------------------强势分隔符--------------------------------
    
            //查询两个集合的差集
            var except = startWithA.Except(endWithE);
            foreach (var item in except)
            {
                Console.WriteLine(item.EmployeeName);
            }
    
            //******************************Output*******************************
            //Adolph
            //Antony
            //Asa
            //*******************************************************************

    Zip:把两个集合中对应的项目合并起来,在到大较小集合的末尾时停止

    //把两个集合中对应的项的姓名合并起来
            var zip = startWithA.Zip(endWithE, (first, second) => first.EmployeeName + "+" + second.EmployeeName);
            foreach (var item in zip)
            {
                Console.WriteLine(item);
            }
    
            //******************************Output*******************************
            //Adolph+Mike
            //Antony+Bernie
            //Asa+Aimee
            //Aimee+Cassie
            //*******************************************************************

    9)元素操作符(First、FirstOrDefault、Last、LastOrDefault、ElementAt、ElementAtOrDefault、Single、SingleOrDefault)

    First:返回第一个满足条件的元素;若不存在,则引发异常。

    FirstOrDefault:返回第一个满足条件的元素;若不存在,则返回默认值。

    //查询年龄大于30岁的第一位员工的姓名
            var first = (from e in employees
                         orderby e.Age
                         select e).First(r => r.Age > 30);
            Console.WriteLine(first.EmployeeName);
    
            //******************************Output*******************************
            //Bernie
            //*******************************************************************

    假设需查询年龄大于50岁的第一位员工的姓名,我们将上述代码中年龄修改为50

    var first = (from e in employees
                         orderby e.Age
                         select e).First(r => r.Age > 50);
            Console.WriteLine(first.EmployeeName);

    执行后发现异常

    此时使用FirstOrDefault操作符:

    //查询年龄大于50岁的第一位员工的姓名,若不存在,则返回N/A
            var firstOrDefault = (from e in employees
                                  orderby e.Age
                                  select e).FirstOrDefault(r => r.Age > 50);
            Console.WriteLine(firstOrDefault == null ? "N/A" : firstOrDefault.EmployeeName);
    
            //******************************Output*******************************
            //N/A
            //*******************************************************************

    Last:返回最后一个满足条件的元素;若不存在,则引发异常。

    LastOrDefault:返回最后一个满足条件的元素;若不存在,则返回默认值。

    ElementAt:返回指定索引位置的元素;若不存在,则引发异常。

    ElementAtOrDefault:返回指定索引位置的元素;若不存在,则返回默认值。

    Single:只返回一个满足条件的元素;若不存在或多个元素都满足条件,则引发异常。

    SingleOrDefault:只返回一个满足条件的元素;若不存在或多个元素都满足条件,则返回默认值。

    10)聚合操作符(Count、Sum、Min、Max、Average、Aggregate)

    Count:返回集合中的项数

    //查找有一个以上爱好的员工的姓名、爱好的数量及部门
            var count = from e in employees
                        let numberHobby = e.Hobby.Count()
                        where numberHobby > 1
                        select new
                        {
                            e.EmployeeName,
                            numberHobby,
                            e.Department
                        };
            foreach (var item in count)
            {
                Console.WriteLine("EmployeeName: " + item.EmployeeName + " NumberHobby: " + item.numberHobby + " Department: " + item.Department);
            }
    
            //******************************Output*******************************
            //EmployeeName: Mike NumberHobby: 2 Department: IT
            //EmployeeName: Adolph NumberHobby: 3 Department: IT
            //EmployeeName: Antony NumberHobby: 2 Department: FD
            //EmployeeName: Carl NumberHobby: 2 Department: QC
            //EmployeeName: Aimee NumberHobby: 2 Department: HR
            //*******************************************************************

    Sum:计算所有值的总和

    Min、Max、Average:最小值、最大值、平均值

    //计算所有员工薪水的总和
            var sum = (from e in employees
                       select e.Salary).Sum/*Min、Max、Average*/();
            Console.WriteLine(sum.ToString("N0"));
    
            //******************************Output*******************************
            //2,149,989
            //*******************************************************************

    Aggregate:对序列进行累加

    //初始值为50000000,依次累加所有员工的薪水
            var aggregate = (from e in employees
                             select e.Salary).Aggregate(5000000, (x, y) => x + y, r => r * 2);
            Console.WriteLine(aggregate.ToString("N0"));
    
            //******************************Output*******************************
            //14,299,978
            //*******************************************************************

    说明:Aggregate扩展方法的第一个参数为初始值。第二个参数是一个表达式,用来对每个元素进行计算(第一个参数是累加变量,第二个参数是当前值)。第三个参数是一个表达式,用来对最终结果进行计算。

    11)转换操作符(ToArray、AsEnumerable、ToList、ToDictionary、Cast<TResult>)

    使用转换操作符会立即执行查询,将查询结果放在数组、列表、字典中。

    //将年龄大于30岁的元素放入list中再循环输出。
            List<Employee> employeeList = (from e in employees
                                           where e.Age > 30
                                           select e).ToList();
            foreach (var item in employeeList)
            {
                Console.WriteLine("EmployeeName: " + item.EmployeeName + " Age:" + item.Age);
            }
    
            //******************************Output*******************************
            //EmployeeName: Mike Age:32
            //EmployeeName: Jack Age:38
            //EmployeeName: Bernie Age:31
            //EmployeeName: Cassie Age:31
            //*******************************************************************

    12)生成操作符(Empty、Range、Repeat)

    生成操作符不是扩展方法,而是返回序列的静态方法。在LINQ to Objects中,这些方法可用于Enumerable类。

    Empty:生成空集合

    //生成一个int类型的空序列
            var empty = Enumerable.Empty<int>();          
            Console.WriteLine(empty.Count());
    
            //******************************Output*******************************
            //0
            //*******************************************************************

    Range:生成一系列数字的集合

    //生成一个从1开始,10个元素的序列
            var range = Enumerable.Range(1, 10);
            foreach (var item in range)
            {
                Console.WriteLine(item);
            }
    
            //******************************Output*******************************
            //1
            //2
            //3
            //4
            //5
            //6
            //7
            //8
            //9
            //10
            //*******************************************************************

    Repeat:返回始终重复一个值的集合

    //生成一个10个元素,每个元素都是5的序列
            var repeat = Enumerable.Repeat(5, 10);
            foreach (var item in repeat)
            {
                Console.WriteLine(item);
            }
    
            //******************************Output*******************************
            //5
            //5
            //5
            //5
            //5
            //5
            //5
            //5
            //5
            //5
            //*******************************************************************

    本篇就此结束,主要介绍了LINQ的体系结构、基本语法以及LINQ to Obejcts中标准查询操作符的使用方法。

    示例代码下载: https://github.com/Answer-Geng/LINQ

  • 相关阅读:
    片段
    告诉长夜
    明天
    开源一个WEB版本GEF,基于SVG的网页流程图框架
    RCP:ISourceLocator翻译
    SVG:textPath深入理解
    SVG:linearGradient渐变在直线上失效的问题解决方案
    【半平面交】BZOJ2618[Cqoi2006]凸多边形
    【旋转卡壳+凸包】BZOJ1185:[HNOI2007]最小矩形覆盖
    【凸包+旋转卡壳】平面最远点对
  • 原文地址:https://www.cnblogs.com/sjqq/p/6900034.html
Copyright © 2020-2023  润新知