C#系列之LINQ 深度解析:优雅查询数据的艺术

目录

前言

一、LINQ 初探:基本概念与优势

1.1 什么是 LINQ?

1.2 LINQ 的优势

二、LINQ 查询语法基础

2.1 使用 from...select 语法

2.2 延迟执行

三、LINQ 常用操作符

3.1 筛选操作符 Where

3.2 投影操作符 Select

3.4 分组操作符 GroupBy

3.5 聚合操作符 Sum、Average、Max、Min

四、LINQ 方法语法与查询语法对比

4.1 查询语法示例

4.2 方法语法示例

五、LINQ 高级特性

5.1 连接操作符 Join

5.2 分区操作符 Skip 和 Take

5.3 集合操作符 Union、Intersect、Except

六、总结


前言

在 C# 的世界中,LINQ(Language Integrated Query,语言集成查询)是一项革命性的技术,它为数据查询和操作提供了一种统一、声明式的方式。无论是操作内存中的集合、数据库中的数据,还是 XML、JSON 等其他数据源,LINQ 都能让代码更加简洁、易读且易于维护。本文将带你深入了解 LINQ 的用法,从基础到高级,感受它的魅力。

一、LINQ 初探:基本概念与优势

1.1 什么是 LINQ

LINQ 是一组扩展方法,它允许你使用类似 SQL 的语法来查询各种数据源。LINQ 查询表达式被编译为方法调用,这些方法可以针对不同的数据源实现。

1.2 LINQ 的优势

  • 统一语法:无论数据源是集合、数据库还是其他类型,都可以使用相同的 LINQ 语法进行查询。
  • 类型安全:在编译时就能发现错误,而不是在运行时。
  • 可读性强:LINQ 查询表达式接近自然语言,易于理解和维护。
  • 可组合性:可以将多个 LINQ 查询组合在一起,形成更复杂的查询。

二、LINQ 查询语法基础

2.1 使用 from...select 语法

这是 LINQ 中最常用的查询语法,类似于 SQL 的 SELECT 语句。

using System;
using System.Linq;    // 命名空间包含了许多用于实现 LINQ 功能的扩展方法
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        List<string> names = new List<string> { "Alice", "Bob", "Charlie", "David" };

        // 查询以字母 'A' 开头的名字
        var query = from name in names
                    where name.StartsWith("A")
                    select name;

        foreach (var name in query)
        {
            Console.WriteLine(name);    // 输出: Alice
        }
    }
}


2.2 延迟执行

LINQ 查询是延迟执行的,这意味着查询在枚举结果之前不会实际执行,你需要以某种方式枚举它,他才得以真正地被执行。这可以提高性能,特别是在处理大量数据时。

List<int> numbers = Enumerable.Range(1, 100).ToList();

var evenNumbersQuery = from num in numbers
                      where num % 2 == 0
                      select num;

// 此时查询尚未执行
Console.WriteLine("Query created but not executed yet.");

// 枚举结果时查询执行
foreach (var num in evenNumbersQuery)
{
    Console.WriteLine(num); // 输出 2, 4, 6, ..., 100
}

三、LINQ 常用操作符

3.1 筛选操作符 Where

Where 操作符用于根据条件筛选元素。

List<int> numbers = Enumerable.Range(1, 10).ToList();

IEnumerable<int> filteredNumbers = numbers.Where(num => num > 5);

foreach (var num in filteredNumbers)
{
    Console.WriteLine(num); // 输出 6, 7, 8, 9, 10
}


3.2 投影操作符 Select

Select 操作符用于将序列中的每个元素投影到一个新的形式。

List<string> names = new List<string> { "Alice", "Bob", "Charlie" };

var nameLengths = names.Select(name => name.Length);

foreach (var length in nameLengths)
{
    Console.WriteLine(length); // 输出 5, 3, 7
}


3.3 排序操作符 OrderBy 和 ThenBy

OrderBy 用于按指定键对序列进行升序排序,ThenBy 用于在主排序后进行次级排序。

class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}
List<Person> people = new List<Person>
{
    new Person { Name = "Alice", Age = 25 },
    new Person { Name = "Bob", Age = 20 },
    new Person { Name = "Charlie", Age = 25 }
};

// 按年龄升序排序,年龄相同则按姓名升序排序
var sortedPeople = people.OrderBy(p => p.Age).ThenBy(p => p.Name);

foreach (var person in sortedPeople)
{
    Console.WriteLine($"{person.Name}, {person.Age}");
    // 输出:
    // Bob, 20
    // Alice, 25
    // Charlie, 25
}

拓展: 按年龄降序排序,年龄相同则按姓名降序排序

 var sortedPeople = people.OrderByDescending(p => p.Age).ThenByDescending(p => p.Name);


3.4 分组操作符 GroupBy

GroupBy 用于将序列中的元素按指定键进行分组。

List<Person> people = new List<Person>
{
    new Person { Name = "Alice", Department = "HR" },
    new Person { Name = "Bob", Department = "IT" },
    new Person { Name = "Charlie", Department = "HR" }
};

var groupedByDepartment = people.GroupBy(p => p.Department);

foreach (var group in groupedByDepartment)
{
    Console.WriteLine($"Department: {group.Key}");
    foreach (var person in group)
    {
        Console.WriteLine($"  {person.Name}");
    }
    // 输出:
    // Department: HR
    //   Alice
    //   Charlie
    // Department: IT
    //   Bob
}

3.5 聚合操作符 SumAverageMaxMin

这些操作符用于对序列中的元素进行聚合计算。

List<int> numbers = Enumerable.Range(1, 5).ToList();

int sum = numbers.Sum(); // 求和
double average = numbers.Average(); // 平均值
int max = numbers.Max(); // 最大值
int min = numbers.Min(); // 最小值

Console.WriteLine($"Sum: {sum}, Average: {average}, Max: {max}, Min: {min}");
// 输出: Sum: 15, Average: 3, Max: 5, Min: 1

四、LINQ 方法语法与查询语法对比

LINQ 提供了两种语法:查询语法方法语法。查询语法更接近 SQL,而方法语法则更接近传统的 C# 方法调用。

4.1 查询语法示例


	var querySyntax = from num in numbers

	where num % 2 == 0

	select num * 2;

4.2 方法语法示例

var methodSyntax = numbers.Where(num => num % 2 == 0).Select(num => num * 2);

两种语法在功能上是等价的,选择哪种语法主要取决于个人偏好和代码的可读性。


五、LINQ 高级特性

5.1 连接操作符 Join

Join 用于将两个序列基于指定的键进行连接。

List<Student> students = new List<Student>
{
    new Student { Id = 1, Name = "Alice" },
    new Student { Id = 2, Name = "Bob" }
};


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


var joinedData = from student in students
join enrollment in enrollments on student.Id equals enrollment.StudentId
select new { student.Name, enrollment.Course };


foreach (var item in joinedData)
{
    Console.WriteLine($"{item.Name} is enrolled in {item.Course}");
    // 输出:
    // Alice is enrolled in Math
    // Bob is enrolled in Science
}


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


class Enrollment
{
    public int StudentId { get; set; }
    public string Course { get; set; }
}

5.2 分区操作符 Skip 和 Take

Skip 用于跳过序列中的前 N 个元素,Take 用于从序列中获取前 N 个元素。这两个操作符常用于分页。

List<int> numbers = Enumerable.Range(1, 20).ToList();


// 获取第二页的数据(每页 5 条记录)
int pageSize = 5;
int pageNumber = 2;
var pagedData = numbers.Skip((pageNumber - 1) * pageSize).Take(pageSize);


foreach (var num in pagedData)
{
    Console.WriteLine(num); // 输出 6, 7, 8, 9, 10
}

5.3 集合操作符 UnionIntersectExcept

这些操作符用于对集合进行并集、交集和差集操作。

List<int> set1 = new List<int> { 1, 2, 3, 4 };

List<int> set2 = new List<int> { 3, 4, 5, 6 };



var union = set1.Union(set2); // 并集: 1, 2, 3, 4, 5, 6

var intersect = set1.Intersect(set2); // 交集: 3, 4

var except = set1.Except(set2); // 差集(set1 - set2): 1, 2



Console.WriteLine("Union:");

foreach (var num in union) Console.Write(num + " "); // 输出: Union: 1 2 3 4 5 6


Console.WriteLine("\nIntersect:");

foreach (var num in intersect) Console.Write(num + " "); // 输出: Intersect: 3 4


Console.WriteLine("\nExcept:");

foreach (var num in except) Console.Write(num + " "); // 输出: Except: 1 2

六、总结

LINQ 是 C# 中一项非常强大的功能,它极大地简化了数据查询和操作的代码。通过本文的介绍,你应该已经对 LINQ 的基本概念、常用操作符、与数据库的集成以及高级特性有了深入的了解。

在实际开发中,合理使用 LINQ 可以让你的代码更加简洁、易读且易于维护。无论是处理内存中的集合还是数据库中的数据,LINQ 都能提供一种统一、高效的方式。希望本文能帮助你更好地掌握 LINQ,并在你的项目中发挥它的优势。

友友们如果对LINQ操作SQL数据库有兴趣的话,欢迎在评论区留言,后续我可以做一期详细教学。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值