C#语言中的 LINQ 基础应用

作者:微信公众号:【架构师老卢】
11-19 19:3
50

语言集成查询(Language Integrated Query,简称 LINQ)是 C# 最强大的特性之一。它允许开发人员直接在 C# 语言中编写查询语句,以便对来自不同数据源(如集合、数据库、XML 文档等)的数据进行操作和查询。LINQ 通过提供一种统一且可读性强的方式来查询和转换数据,让处理数据变得更加容易。

本篇博客将逐步引导你了解 LINQ 的基础知识,从语法开始,再到更高级的主题,都会以通俗易懂的方式进行讲解。

为何使用 LINQ?

在深入探讨语法之前,让我们先来了解一下 LINQ 为何如此重要:

  • 统一的语法:LINQ 为查询不同的数据源(例如数组、列表、XML、数据库)提供了统一的语法。
  • 可读性强:LINQ 查询通常比等效的循环或其他代码结构更具可读性且更为简洁。
  • 强类型:LINQ 集成于 C# 之中,这意味着你能获得编译时检查以及智能感知(IntelliSense)支持。
  • 声明式方法:LINQ 允许你描述想要对数据执行的操作,而非说明如何去做,从而使代码更加清晰且更易于维护。

LINQ 的基本概念

在开始编写 LINQ 查询之前,让我们先来了解一些基本概念。

  • 数据源:你想要查询的数据集合或序列。它可以是一个数组、列表、数据库表等等。
  • 查询:你定义的一组用于从数据源中获取所需数据的操作。
  • 执行:当查询运行时,它会根据查询条件从数据源中提取数据。

LINQ 入门

让我们从一个简单的示例开始。假设我们有一个整数列表,并且想要找出其中所有的偶数。

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

class Program
{
    static void Main()
    {
        // 数据源
        List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

        // LINQ 查询
        var evenNumbers = from num in numbers
                          where num % 2 == 0
                          select num;

        // 执行
        foreach (var num in evenNumbers)
        {
            Console.WriteLine(num);
        }
    }
}

解释

  • 数据源numbers 就是我们的数据源,它是一个整数列表。
  • 查询:LINQ 查询以 from 关键字开头,后面跟着 whereselect 子句。
    • from num in numbers:遍历 numbers 列表中的每一项。
    • where num % 2 == 0:筛选出能被 2 整除的数字(即偶数)。
    • select num:选择符合条件的数字。

当你运行这段代码时,它将输出:

2
4
6
8
10

LINQ 语法

LINQ 提供了两种语法类型:

  • 查询语法:这种语法类似于 SQL,对于熟悉 SQL 的人来说可读性更强。

示例

var evenNumbers = from num in numbers
                  where num % 2 == 0
                  select num;
  • 方法语法:这种语法更为紧凑,常用于方法链中。
var evenNumbers = numbers.Where(num => num % 2 == 0);

这两种语法是等效的,你可以根据自己觉得哪种更具可读性来选择使用。

LINQ 的关键操作符

LINQ 提供了丰富的操作符来操作数据。以下是一些最常用的操作符:

  • Where:基于某个条件对元素进行筛选。
var evenNumbers = numbers.Where(num => num % 2 == 0);
  • Select:将一个序列中的每个元素投影为新的形式。
var squares = numbers.Select(num => num * num);
  • OrderBy / OrderByDescending:按升序或降序对元素进行排序。
var sortedNumbers = numbers.OrderBy(num => num);
  • GroupBy:根据共同的属性对元素进行分组。
var groupedNumbers = numbers.GroupBy(num => num % 2);
  • Join:基于某个键将两个序列进行连接。
var joinedData = from num in numbers
                 join num2 in otherNumbers on num equals num2
                 select new { num, num2 };
  • Aggregate:对序列中的每个元素执行一个操作,并返回单个结果。
var sum = numbers.Aggregate((a, b) => a + b);

处理不同的数据源

LINQ 并不局限于集合,它还可以查询各种数据源,例如:

  • LINQ to Objects:用于查询像数组、列表等集合。
var result = from num in numbers where num > 5 select num;
  • LINQ to SQL:用于查询关系型数据库。
var query = from p in context.Products where p.Price > 100 select p;
  • LINQ to XML:用于查询 XML 文档。
var xmlQuery = from x in xmlDoc.Elements("Book") where (string)x.Element("Author") == "AuthorName" select x;
  • LINQ to Entities:用于查询实体框架模型。
var xmlQuery = from x in xmlDoc.Elements("Book") where (string)x.Element("Author") == "AuthorName" select x;

延迟执行与立即执行

LINQ 中的一个重要概念是延迟执行。LINQ 查询在定义时并不会执行,而是在对其进行迭代(例如使用 foreach 循环)时才会执行,这被称为延迟执行。

var query = from num in numbers where num > 5 select num;
// 此处查询并未执行

foreach (var num in query)
{
    Console.WriteLine(num); // 在此处查询才执行
}

当调用像 ToList()ToArray()First()Count() 等方法时,会立即执行查询,这就是立即执行。

var immediateExecution = numbers.Where(num => num > 5).ToList(); // 立即执行

LINQ 的高级特性

  • 匿名类型:LINQ 允许你直接在查询中创建匿名类型。
var results = from num in numbers
              select new { Number = num, Square = num * num };
  • Let 关键字:允许你将子查询的结果存储在一个变量中,以便在同一个查询内重复使用。
var result = from num in numbers
             let square = num * num
             where square > 10
             select square;
  • Join:用于基于一个公共键合并多个数据源。
var joinResult = from p in products
                 join c in categories on p.CategoryId equals c.Id
                 select new { p.Name, c.CategoryName };
  • GroupJoin:合并数据并对结果进行分组。
var groupJoin = from c in categories
                join p in products on c.Id equals p.CategoryId into productGroup
                select new { c.CategoryName, Products = productGroup };
  • Cross Join:将一个数据源的每个元素与另一个数据源的每个元素进行组合。
var crossJoin = from p in products
                from c in categories
                select new { p.Name, c.CategoryName };
  • Zip:通过根据元素位置合并两个序列的元素来将它们进行组合。
var zipped = numbers.Zip(otherNumbers, (first, second) => first + second);

LINQ 的最佳实践

  • 对于复杂查询使用方法语法:方法语法功能更强大且更简洁,尤其适用于复杂查询。
  • 避免重复查询:如果你需要多次使用查询结果,应存储该结果以避免性能问题。
  • 明智地使用延迟执行:了解查询何时执行,以避免出现意外行为。
  • 优化性能:考虑查询对性能的影响,特别是在处理大型数据集或执行复杂操作时。

LINQ 是 C# 中一个强大的工具,它让处理数据变得更加直观且具有可读性。无论你是查询集合、数据库还是 XML,LINQ 都提供了一种统一的方式来处理数据。通过理解并掌握 LINQ,你可以编写更高效、更易于维护且更简洁的代码。

相关留言评论
昵称:
邮箱:
阅读排行