C# LINQ 用法详解

一、LINQ 概念
语言集成查询(LINQ)

LINQ 是一种统一的查询语法,它允许使用类似 SQL 的语法来查询各种数据源,如集合、数据库、XML 等。它将查询能力直接集成到 C# 语言中。

LINQ 提供程序

是实现 LINQ 语法与特定数据源之间转换的组件。例如,LINQ to Objects 用于查询内存中的集合对象;LINQ to SQL 用于查询 SQL Server 数据库;LINQ to XML 用于查询 XML 数据。

数据源

是 LINQ 查询操作的对象,可以是数组、列表、数据库表、XML 文档等。它提供了数据供查询使用。

查询表达式

是使用 LINQ 语法编写的代码片段,用于从数据源中检索数据。它通常以 from、where、select 等关键字开头,以 select 或 group 关键字结尾。

延迟执行(Deferred Execution)

LINQ 查询的执行被延迟到实际获取查询结果时才进行。这意味着查询的定义和执行是分离的,只有在需要实际结果时(如通过 foreach 遍历结果或使用 ToList() 等方法)才会执行查询。

立即执行(Immediate Execution)

与延迟执行相对,有些 LINQ 操作符(如 ToList()、ToArray()、Count() 等)会立即执行查询并返回结果。

二、LINQ 类别及用法
LINQ to Objects

概念 :用于查询内存中的集合对象,如数组、列表等。

示例代码

using System;
using System.Collections.Generic;
using System.Linq;

namespace LinqToObjectsExample
{
    class Program
    {
        static void Main(string[] args)
        {
            // 创建一个整数列表
            List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

            // 查询大于 5 的数字
            var result = from num in numbers
                         where num > 5
                         select num;

            // 遍历查询结果
            foreach (var item in result)
            {
                Console.WriteLine(item);
            }

            // 立即执行查询并转换为列表
            List<int> resultList = numbers.Where(n => n > 5).ToList();

            foreach (int item in resultList)
            {
                Console.WriteLine(item);
            }
        }
    }
}

LINQ to SQL

概念 :用于查询 SQL Server 数据库。它提供了一种对象关系映射(O/RM)的方式,将数据库表映射为 C# 类。

示例代码(需要添加 System.Data.Linq 引用)

using System;
using System.Linq;

namespace LinqToSqlExample
{
    class Program
    {
        static void Main(string[] args)
        {
            // 创建数据库连接上下文
            using (var db = newDataContext("Your_Connection_String"))
            {
                // 查询所有 Product 表中的产品,价格大于 100
                var products = from p in db.Products
                               where p.Price > 100
                               select p;

                foreach (var product in products)
                {
                    Console.WriteLine($"{product.Name}: {product.Price}");
                }
            }
        }
    }

    // 数据库上下文类
    public class DataContext : System.Data.Linq.DataContext
    {
        public DataContext(string connection) : base(connection) { }
        public System.Data.Linq.Table<Product> Products;
    }

    // 产品类(映射数据库表)
    public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public decimal Price { get; set; }
    }
}

LINQ to XML

概念 :用于查询和操作 XML 数据。它提供了一组丰富的 API 来创建、修改、查询 XML 文档。

示例代码

using System;
using System.Linq;
using System.Xml.Linq;

namespace LinqToXmlExample
{
    class Program
    {
        static void Main(string[] args)
        {
            // 创建 XML 文档
            XElement xml = new XElement("Students",
                new XElement("Student",
                    new XElement("Name", "John"),
                    new XElement("Age", 20)),
                new XElement("Student",
                    new XElement("Name", "Jane"),
                    new XElement("Age", 22))
            );

            // 查询年龄大于 20 的学生
            var students = from student in xml.Elements("Student")
                           let age = int.Parse(student.Element("Age").Value)
                           where age > 20
                           select student.Element("Name").Value;

            foreach (var student in students)
            {
                Console.WriteLine(student);
            }
        }
    }
}

不过上面代码中的查询语句也可以改为lambda 表达式风格来写,例如:

var students = xml.Elements("Student")
                  .Where(s => int.Parse(s.Element("Age").Value) > 20)
                  .Select(s => s.Element("Name").Value);

效果是一样的。

LINQ 标准查询操作符

  • 过滤操作符
    • Where :用于根据条件过滤元素。
    • 示例代码
using System;
using System.Collections.Generic;
using System.Linq;

namespace WhereExample
{
    class Program
    {
        static void Main(string[] args)
        {
            List<string> fruits = new List<string> { "Apple", "Banana", "Cherry", "Date" };

            // 查询以 'A' 开头的水果
            var fruitsWithA = fruits.Where(fruit => fruit.StartsWith("A"));

            foreach (var fruit in fruitsWithA)
            {
                Console.WriteLine(fruit);
            }
        }
    }
}
  • 选择操作符
    • Select :用于投影元素,将每个元素转换为新的形式。
    • 示例代码
using System;
using System.Collections.Generic;
using System.Linq;

namespace SelectExample
{
    class Program
    {
        static void Main(string[] args)
        {
            List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };

            // 将数字投影为它们的平方
            var squares = numbers.Select(num => num * num);

            foreach (var square in squares)
            {
                Console.WriteLine(square);
            }
        }
    }
}
  • 排序操作符
    • OrderBy :用于按升序排序元素。
    • OrderByDescending :用于按降序排序元素。
    • ThenBy :用于在主要排序的基础上进行次要排序。
    • ThenByDescending :用于在主要排序的基础上进行次要降序排序。
    • 示例代码

using System;
using System.Collections.Generic;
using System.Linq;

namespace OrderByExample
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Student> students = new List<Student>
            {
                new Student{ Name = "John", Age = 20 },
                new Student{ Name = "Jane", Age = 22 },
                new Student{ Name = "Bob", Age = 19 }
            };

            // 按年龄升序排序学生
            var sortedStudents = students.OrderBy(student => student.Age);

            foreach (var student in sortedStudents)
            {
                Console.WriteLine($"{student.Name}: {student.Age}");
            }

            // 按年龄降序排序学生
            var sortedStudentsDescending = students.OrderByDescending(student => student.Age);

            foreach (var student in sortedStudentsDescending)
            {
                Console.WriteLine($"{student.Name}: {student.Age}");
            }

            // 按年龄升序排序,然后按姓名降序排序
            var sortedStudentsThenBy = students.OrderBy(student => student.Age).ThenByDescending(student => student.Name);

            foreach (var student in sortedStudentsThenBy)
            {
                Console.WriteLine($"{student.Name}: {student.Age}");
            }
        }
    }

    public class Student
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }
}
  • 聚合操作符
    • Count :用于计算集合中的元素个数。
    • Sum :用于计算集合中元素的总和。
    • Average :用于计算集合中元素的平均值。
    • Max :用于获取集合中的最大值。
    • Min :用于获取集合中的最小值。
    • 示例代码
using System;
using System.Collections.Generic;
using System.Linq;

namespace AggregateExample
{
    class Program
    {
        static void Main(string[] args)
        {
            List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6 };

            // 计算元素个数
            int count = numbers.Count();
            Console.WriteLine($"Count: {count}");

            // 计算总和
            int sum = numbers.Sum();
            Console.WriteLine($"Sum: {sum}");

            // 计算平均值
            double average = numbers.Average();
            Console.WriteLine($"Average: {average}");

            // 获取最大值
            int max = numbers.Max();
            Console.WriteLine($"Max: {max}");

            // 获取最小值
            int min = numbers.Min();
            Console.WriteLine($"Min: {min}");
        }
    }
}
  • 分组操作符
    • GroupBy :用于根据指定的键将元素分组。
    • 示例代码
using System;
using System.Collections.Generic;
using System.Linq;

namespace GroupByExample
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Student> students = new List<Student>
            {
                new Student{ Name = "John", Grade = "A" },
                new Student{ Name = "Jane", Grade = "B" },
                new Student{ Name = "Bob", Grade = "A" }
            };

            // 按成绩分组学生
            var groupedStudents = students.GroupBy(student => student.Grade);

            foreach (var group in groupedStudents)
            {
                Console.WriteLine($"Grade: {group.Key}");
                foreach (var student in group)
                {
                    Console.WriteLine(student.Name);
                }
            }
        }
    }

    public class Student
    {
        public string Name { get; set; }
        public string Grade { get; set; }
    }
}
  • 连接操作符
    • Join :用于将两个集合中的元素基于键进行连接。
    • 示例代码
using System;
using System.Collections.Generic;
using System.Linq;

namespace JoinExample
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Student> students = new List<Student>
            {
                new Student{ Id = 1, Name = "John" },
                new Student{ Id = 2, Name = "Jane" }
            };

            List<Course> courses = new List<Course>
            {
                new Course{ StudentId = 1, CourseName = "Math" },
                new Course{ StudentId = 2, CourseName = "Science" }
            };

            // 将学生和课程进行连接
            var studentCourses = from student in students
                                 join course in courses on student.Id equals course.StudentId
                                 select new { student.Name, course.CourseName };

            foreach (var item in studentCourses)
            {
                Console.WriteLine($"{item.Name}: {item.CourseName}");
            }
        }
    }

    public class Student
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

    public class Course
    {
        public int StudentId { get; set; }
        public string CourseName { get; set; }
    }
}
  • 集合操作符
    • Union :用于合并两个集合,并返回去重后的结果。
    • Intersect :用于获取两个集合的交集。
    • Except :用于获取两个集合的差集。
    • Concat :用于合并两个集合(不去重)。
    • 示例代码
using System;
using System.Collections.Generic;
using System.Linq;

namespace SetExample
{
    class Program
    {
        static void Main(string[] args)
        {
            List<int> list1 = new List<int> { 1, 2, 3, 4 };
            List<int> list2 = new List<int> { 3, 4, 5, 6 };

            // 合并两个集合并去重
            var union = list1.Union(list2);
            Console.WriteLine("Union:");
            foreach (var item in union)
            {
                Console.WriteLine(item);
            }

            // 获取交集
            var intersect = list1.Intersect(list2);
            Console.WriteLine("\nIntersect:");
            foreach (var item in intersect)
            {
                Console.WriteLine(item);
            }

            // 获取差集(list1 中有而 list2 中没有的元素)
            var except = list1.Except(list2);
            Console.WriteLine("\nExcept:");
            foreach (var item in except)
            {
                Console.WriteLine(item);
            }

            // 合并两个集合(不去重)
            var concat = list1.Concat(list2);
            Console.WriteLine("\nConcat:");
            foreach (var item in concat)
            {
                Console.WriteLine(item);
            }
        }
    }
}
  • 转换操作符
    • OfType :用于过滤并转换集合中的元素类型。
    • Cast :用于将集合中的元素强制转换为指定类型。
    • ToList :用于将集合转换为列表。
    • ToArray :用于将集合转换为数组。
    • ToDictionary :用于将集合转换为字典。
    • 示例代码
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

namespace ConvertExample
{
    class Program
    {
        static void Main(string[] args)
        {
            ArrayList mixedList = new ArrayList { 1, "John", 2, "Jane", 3 };

            // 筛选整数并转换为列表
            List<int> intList = mixedList.OfType<int>().ToList();

            foreach (var item in intList)
            {
                Console.WriteLine(item);
            }

            // 将集合转换为字典
            var dict = mixedList.OfType<int>().ToDictionary(x => x, x => x * 2);

            foreach (var keyValuePair in dict)
            {
                Console.WriteLine($"{keyValuePair.Key}: {keyValuePair.Value}");
            }
        }
    }
}
  • 元素操作符
    • First :用于获取集合中的第一个元素。
    • FirstOrDefault :用于获取集合中的第一个元素,如果集合为空,则返回默认值。
    • Last :用于获取集合中的最后一个元素。
    • LastOrDefault :用于获取集合中的最后一个元素,如果集合为空,则返回默认值。
    • Single :用于获取集合中唯一的元素,如果集合中没有元素或有多个元素则抛出异常。
    • SingleOrDefault :用于获取集合中唯一的元素,如果集合为空则返回默认值,如果有多个元素则抛出异常。
    • ElementAt :用于获取集合中指定索引的元素。
    • ElementAtOrDefault :用于获取集合中指定索引的元素,如果索引超出范围则返回默认值。
    • 示例代码
using System;
using System.Collections.Generic;
using System.Linq;

namespace ElementExample
{
    class Program
    {
        static void Main(string[] args)
        {
            List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };

            // 获取第一个元素
            int first = numbers.First();
            Console.WriteLine($"First: {first}");

            // 获取最后一个元素
            int last = numbers.Last();
            Console.WriteLine($"Last: {last}");

            // 获取唯一元素(如果有多个元素会抛异常)
            List<int> singleList = new List<int> { 1 };
            int single = singleList.Single();
            Console.WriteLine($"Single: {single}");

            // 获取指定索引的元素
            int elementAt = numbers.ElementAt(2);
            Console.WriteLine($"ElementAt: {elementAt}");
        }
    }
}
  • 生成操作符
    • DefaultIfEmpty :用于如果集合为空,则返回一个包含默认值的集合。
    • Empty :用于创建一个空的集合。
    • Range :用于生成一个数字序列。
    • Repeat :用于生成一个包含重复元素的集合。
    • 示例代码
using System;
using System.Linq;

namespace GenerateExample
{
    class Program
    {
        static void Main(string[] args)
        {
            List<int> emptyList = new List<int>();

            // 如果集合为空,返回包含默认值的集合
            var defaultIfEmpty = emptyList.DefaultIfEmpty(0);
            Console.WriteLine("DefaultIfEmpty:");
            foreach (var item in defaultIfEmpty)
            {
                Console.WriteLine(item);
            }

            // 生成一个数字序列
            var range = Enumerable.Range(1, 5);
            Console.WriteLine("\nRange:");
            foreach (var item in range)
            {
                Console.WriteLine(item);
            }

            // 生成一个包含重复元素的集合
            var repeat = Enumerable.Repeat("Hello", 3);
            Console.WriteLine("\nRepeat:");
            foreach (var item in repeat)
            {
                Console.WriteLine(item);
            }
        }
    }
}

暧昧贴

发表评论

    微笑 大笑 拽 大哭 奸笑 流汗 喷血 生气 囧 不爽 晕 示爱 卖萌 吃惊 迷离 爱你 吓死了 呵呵