导读:本期聚焦于苹果创作的《C#中如何使用LINQ查询集合数据?LINQ基本用法详解》,敬请观看详情。刚接触C#的开发者常会困惑:数组和List里的数据,除了写foreach循环逐个判断,还有没有更简洁高效的筛选方式?这正是LINQ要解决的问题。LINQ即语言集成查询,它把查询能力直接集成到C#语法中,让集合筛选、排序、分组和投影都可以用统一的表达式完成。本文从最常用的Where、Select、OrderBy、GroupBy等方法入手,说明延迟执行与立即执行的区别,并给出针对List和数组的完整示例。掌握这些基础用法后,处理内存中的集合数据时,代码量通常能明显减少,可读性也会更好。文中示例均基于控制台应用,便于直接复制运行验证。对刚接触LINQ的读者来说,先理解方法语法的链式调用会更容易上手。

在C#中处理数组、List或者自定义对象集合时,如果每次都手写foreach加if条件,代码会变得冗长,筛选逻辑一多还容易出错。LINQ提供了一种声明式的数据查询方式,开发者只需描述“要什么数据”,而不必关心“怎么遍历和判断”。本文围绕LINQ查询内存集合数据的常用写法展开,帮助读者快速上手。

C#中如何使用LINQ查询集合数据?LINQ基本用法详解

一、LINQ的两种语法:查询表达式与方法语法

LINQ在C#中有两种等价的书写方式。查询表达式使用from、where、orderby、select等关键字,形式上接近SQL;方法语法则直接调用Where、Select、OrderBy等扩展方法,并通过链式调用组合多个操作。两种写法最终都会转换成方法调用,因此底层行为完全一致。

先看一个针对整数集合的简单例子。下面的代码分别用两种语法筛选大于8的数字,并按降序输出。使用LINQ前需要引入System.Linq命名空间,否则扩展方法无法使用。

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

class Program
{
    static void Main()
    {
        List<int> numbers = new List<int> { 3, 10, 7, 20, 5, 15 };

        // 查询表达式写法
        var queryResult = from n in numbers
                          where n > 8
                          orderby n descending
                          select n;

        // 方法语法写法
        var methodResult = numbers.Where(n => n > 8).OrderByDescending(n => n);

        Console.WriteLine("查询表达式结果:");
        foreach (var item in queryResult)
        {
            Console.WriteLine(item);
        }

        Console.WriteLine("方法语法结果:");
        foreach (var item in methodResult)
        {
            Console.WriteLine(item);
        }
    }
}

查询表达式在涉及join、group等复杂逻辑时,结构更加直观;方法语法则更容易与链式API配合,也便于动态拼接查询条件。对于入门阶段,建议先把方法语法练熟,因为它在实际项目中出现的频率更高。LINQ可以作用于任何实现了IEnumerable<T>接口的对象,数组、List<T>、字典的值集合等都属于这一类。

二、核心操作符:Where、Select和OrderBy

Where是最常用的筛选操作符,它接收一个Func<T, bool>委托,只为返回true的元素放行。下面以商品列表为例,筛选价格大于200的商品。先定义一个简单的Product类。

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

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
    public string Category { get; set; }
}

class Program
{
    static void Main()
    {
        List<Product> products = new List<Product>
        {
            new Product { Id = 1, Name = "机械键盘", Price = 399m, Category = "外设" },
            new Product { Id = 2, Name = "显示器", Price = 1299m, Category = "显示设备" },
            new Product { Id = 3, Name = "鼠标", Price = 199m, Category = "外设" },
            new Product { Id = 4, Name = "USB集线器", Price = 89m, Category = "配件" }
        };

        var expensive = products.Where(p => p.Price > 200).ToList();

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

Select用于投影,它可以把集合中的元素转换成另一种形状。例如只想获取商品名称和价格,可以返回一个匿名类型,避免创建多余的DTO类。OrderBy与OrderByDescending用于排序,如果存在多个排序条件,可以用ThenBy或ThenByDescending继续追加。

var namesAndPrices = products
    .Select(p => new { p.Name, p.Price });

var sortedProducts = products
    .OrderBy(p => p.Category)
    .ThenByDescending(p => p.Price);

foreach (var item in sortedProducts)
{
    Console.WriteLine($"{item.Category} - {item.Name} - {item.Price}");
}

这些操作符返回的是IEnumerable<T>,并且大部分都具有延迟执行的特点。也就是说,定义查询时不会立刻遍历集合,只有真正需要结果时才开始计算。这样做的好处是可以把多次操作合并成一次遍历,坏处是如果多次枚举同一个查询,每次都会重新执行逻辑。若希望保存一次查询结果,应在末尾调用ToList或ToArray。

三、GroupBy分组与聚合统计

GroupBy可以按照某个键把集合划分成多个分组。比如将商品按类目分组,观察每个类别下有哪些商品。分组后每一个组的Key就是分组键,组内元素仍可继续遍历。

var groups = products.GroupBy(p => p.Category);

foreach (var group in groups)
{
    Console.WriteLine($"分类:{group.Key}");
    foreach (var product in group)
    {
        Console.WriteLine($"  {product.Name}");
    }
}

聚合操作符用来做统计计算。Count统计数量,Sum求和,Average求平均值,Min和Max取最小值和最大值。它们会立即执行查询,而不是返回延迟序列。例如统计所有商品的平均价格、最贵商品价格和商品总数,可以写成下面这样。

int totalCount = products.Count();
decimal averagePrice = products.Average(p => p.Price);
decimal maxPrice = products.Max(p => p.Price);

Console.WriteLine($"总数:{totalCount}");
Console.WriteLine($"平均价格:{averagePrice:F2}");
Console.WriteLine($"最高价格:{maxPrice}");

此外,Any用于判断集合中是否存在满足条件的元素,All检查是否全部满足条件,Contains判断是否包含指定元素。这些量词操作在编写业务校验逻辑时非常实用。比如判断是否存在价格大于1000的商品,只需products.Any(p => p.Price > 1000),比手写循环直观得多。延迟执行与立即执行的区分在实际排错中也很重要:如果在调试时查看查询结果,记得先调用ToList,否则可能看到的是查询表达式本身,而不是数据。

四、组合使用与常见注意事项

把筛选、排序和投影串在一起,就能形成一条清晰的查询管道。下面这段代码从商品列表中筛选出外设类目且价格超过100元的商品,按价格降序排列,最后只投影名称和价格。整个流程没有手写任何foreach,可读性明显更好。

var result = products
    .Where(p => p.Category == "外设" && p.Price > 100)
    .OrderByDescending(p => p.Price)
    .Select(p => new { p.Name, p.Price });

foreach (var item in result)
{
    Console.WriteLine($"{item.Name} 售价 {item.Price} 元");
}

实际使用中还要注意空集合和不存在元素的情况。First和Single在找不到匹配项时会抛出异常,若不能保证元素一定存在,应当优先使用FirstOrDefault和SingleOrDefault。下面的例子先判断返回结果是否为null,再输出名称,避免空引用异常。

var first = products.FirstOrDefault(p => p.Category == "外设");
if (first != null)
{
    Console.WriteLine(first.Name);
}

另一个容易忽略的问题是源集合为null。如果传入的集合本身是null,调用Where等扩展方法会直接抛出ArgumentNullException。在方法入口处应该先做判空处理,或者使用空集合作为默认值。总体而言,LINQ的价值不只是让代码变短,更重要的是把循环思维转换为查询思维。当需要处理的数据筛选条件越来越多时,这种声明式写法能显著降低维护成本。

掌握了上述基础用法后,可以继续了解Join连接多个集合、SelectMany展开嵌套集合,以及IQueryable在数据库查询中的差异。对于内存集合数据,LINQ to Objects已经能覆盖大部分日常开发场景,熟练运用查询操作符会对提升开发效率很有帮助。

C# LINQ集合查询LINQ基本用法修改时间:2026-09-30 16:44:25

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/0930/63896.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。