C#的LINQ是什么?如何使用它来查询数据集合?

来源:IT编程作者:香港程序员头衔:程序员
导读:本期聚焦于小伙伴创作的《C#的LINQ是什么?如何使用它来查询数据集合?》,敬请观看详情。把一堆循环加判断的筛选逻辑改写成几行声明式语句,代码立刻清爽许多,这背后就是LINQ在起作用。LINQ全称语言集成查询,它把查询能力直接嵌入C#语法,让数组、列表、数据库表都能用同一套写法来过滤与投影。不同于手工写迭代器,LINQ提供延迟执行特性,查询本身不会立刻跑数据,而是在遍历时才真正计算,方便拼接多个条件。掌握from、where、select以及方法语法里的Where、Select,就能应付大多数集合处理场景。文章用具体代码演示如何用LINQ查询内存中的对象集合,并说明链式调用与查询表达式的差异,以及常见的空引用与性能误区。

LINQ是CSharp语言集成查询的缩写,它把数据查询表达为语言的一部分,使开发者可以用类似SQL的语法直接操作内存中的集合、XML文档以及远程数据库。传统做法要写foreach循环加if判断来挑数据,而LINQ把这些操作抽象成标准算子,代码更短也更易懂。

C#的LINQ是什么?如何使用它来查询数据集合?

一、LINQ的基本概念与两种语法

LINQ核心思想是把查询逻辑从具体的数据源中解耦。无论数据是List、数组还是Entity Framework映射的表,都可以用相同的查询算子处理。它主要提供两种写法:查询表达式和方法语法。查询表达式以from开头,看起来接近SQL;方法语法则用点号调用扩展方法,如Where、Select。

查询表达式在编译时会被转换成方法语法,因此两者本质等价。初学者往往觉得查询表达式直观,但在需要复杂链式组合时,方法语法更灵活。理解它们之间的关系,有助于在团队代码中自由切换风格而不产生歧义。

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

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

class Program
{
    static void Main()
    {
        List<Student> students = new List<Student>
        {
            new Student { Name = "张三", Score = 80 },
            new Student { Name = "李四", Score = 55 },
            new Student { Name = "王五", Score = 92 }
        };

        // 查询表达式写法
        var good1 = from s in students
                    where s.Score >= 60
                    select s.Name;

        // 方法语法写法
        var good2 = students.Where(s => s.Score >= 60).Select(s => s.Name);

        foreach (var n in good1) Console.WriteLine(n);
    }
}

延迟执行机制

上面代码中,good1和good2在定义时并不会立刻遍历students。只有进入foreach时,LINQ才真正执行过滤。这种延迟执行意味着如果students后续被修改,查询结果也会反映改动,这既是便利也是陷阱。

若希望立即拿到结果,可以调用ToList或ToArray,把序列物化成具体集合,避免多次枚举带来的重复计算。在写工具方法返回LINQ结果时,明确是否物化能减少调用方的性能疑惑。

二、用LINQ查询常见数据集合

实际项目中,最常处理的是List和数组。LINQ提供大量算子:Where过滤、Select投影、OrderBy排序、GroupBy分组、Any判断存在性。组合这些算子可以替代绝大多数手写循环。

下面示例展示如何对分数分组并统计每档人数,同时按平均分排序。这样的逻辑若用手工循环写,需要多个字典和临时变量,而LINQ几行即可表达清楚。

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

class Program
{
    static void Main()
    {
        List<int> scores = new List<int> { 45, 88, 92, 60, 73, 55, 81 };

        var groups = scores
            .GroupBy(s => s >= 60 ? "及格" : "不及格")
            .Select(g => new
            {
                Level = g.Key,
                Count = g.Count(),
                Average = g.Average()
            })
            .OrderByDescending(x => x.Count);

        foreach (var item in groups)
        {
            Console.WriteLine($"{item.Level}: 人数{item.Count}, 平均{item.Average:F1}");
        }
    }
}

处理引用类型集合

当集合元素是自定义类时,Select可以构造新匿名类型或具体DTO,避免把整个实体暴露给上层。结合Where还能做级联过滤,比如先按班级筛选,再按成绩排序,最后取前三名。

要注意的是,引用类型的默认相等比较基于引用地址。如果在Distinct或分组时使用对象本身,需重写Equals和GetHashCode,或改用Select出值类型键再分组,否则逻辑可能不符合预期。

三、LINQ查询的注意事项与误区

虽然LINQ让代码变短,但不代表总是最快。在超大数据集上多次链式Where会导致多次遍历,此时用单个循环或更优算法更合适。另外,在循环里反复调用同一LINQ查询而未物化,会引起重复计算拖慢程序。

空集合本身不会让LINQ抛异常,但若查询中访问了可能为null的属性,就会触发空引用异常。可以用Where先过滤null,或使用CSharp 6之后的空条件运算符配合Select,写法是select子句内用s?.Name。

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

class Item { public string Tag { get; set; } }

class Program
{
    static void Main()
    {
        List<Item> data = new List<Item> { new Item { Tag = "A" }, null, new Item { Tag = "B" } };

        // 安全写法:先去null再取Tag
        var tags = data
            .Where(x => x != null)
            .Select(x => x.Tag)
            .ToList();

        tags.ForEach(Console.WriteLine);
    }
}

与数据库LINQ提供程序的差异

内存LINQ和EF Core等数据库提供程序虽然语法一致,但前者在本地跑,后者翻译成SQL。某些方法如自定义CSharp函数无法翻译,会报错或强制客户端评估。写查询时应尽量用可翻译的算子,避免把全表拉回内存再过滤。

掌握这些差异后,就能在业务层放心使用LINQ提升可读性,同时在数据访问层留意翻译限制,保证系统整体性能稳定。

LINQCSharp数据查询修改时间:2026-07-31 16:06:35

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