LINQ 基础
LINQ 基础#
LINQ(Language Integrated Query,语言集成查询) 是 C# 内置的查询能力,用统一语法操作集合、数据库、XML 等数据源。核心思想:“筛选—投影—排序—分组” 用声明式写法完成。
1. 两种写法#
List<int> nums = new() { 1, 2, 3, 4, 5, 6 };
// 查询语法(类似 SQL,底层会被编译成方法调用)
var query1 = from n in nums
where n % 2 == 0
orderby n descending
select n * 10;
// 方法语法(Lambda,实际开发更常用)
var query2 = nums.Where(n => n % 2 == 0)
.OrderByDescending(n => n)
.Select(n => n * 10);
// 结果都是 [60, 40, 20]csharp大多数情况推荐方法语法,只有多条件 join/分组时查询语法更易读。
2. 常用操作符速查#
筛选与投影#
list.Where(x => x.Age > 18) // 筛选
list.Select(x => x.Name) // 投影(提取字段/变形)
list.SelectMany(x => x.Tags) // 拍平嵌套集合
list.Distinct() // 去重csharp排序#
list.OrderBy(x => x.Age) // 升序
list.OrderByDescending(x => x.Age) // 降序
list.OrderBy(x => x.Age).ThenBy(x => x.Name) // 多级排序csharp聚合与判断#
nums.Sum() nums.Average() nums.Max() / Min()
nums.Count() nums.Count(x => x > 3) // 带条件计数
nums.Any(x => x > 5) // 是否存在
nums.All(x => x > 0) // 是否全部满足
nums.First() nums.FirstOrDefault() // 取第一个(没找到时后者返回默认值)
nums.Single() nums.SingleOrDefault() // 确保只有一个csharp⚠️ First / Single 找不到元素会抛异常,日常更常用 FirstOrDefault / SingleOrDefault。
分页(搭配常见)#
list.Skip(10).Take(5) // 跳过10条取5条csharp分组与连接#
// 分组
var groups = users.GroupBy(u => u.Dept);
foreach (var g in groups)
Console.WriteLine($"{g.Key}: {g.Count()}人");
// 连接(类似 SQL JOIN)
var result = from u in users
join d in depts on u.DeptId equals d.Id
select new { u.Name, DeptName = d.Name };csharp集合运算#
a.Union(b) // 并集(去重)
a.Intersect(b) // 交集
a.Except(b) // 差集
a.Concat(b) // 拼接(不去重)
a.Contains(x) // 是否包含csharp3. 综合实战#
public class Student
{
public string Name { get; set; }
public string ClassName { get; set; }
public int Score { get; set; }
}
List<Student> students = GetStudents();
// 需求:各班平均分前3名,只要姓名和分数
var top3 = students
.GroupBy(s => s.ClassName)
.Select(g => new
{
班级 = g.Key,
平均分 = g.Average(s => s.Score),
前三 = g.OrderByDescending(s => s.Score)
.Take(3)
.Select(s => new { s.Name, s.Score })
})
.OrderByDescending(x => x.平均分);csharpLINQ 返回的 IEnumerable<T> 常配合匿名类型输出,无需预先定义结果类。
4. 延迟执行(重要概念!)#
var query = nums.Where(n => { Console.WriteLine($"检查{n}"); return n > 2; });
Console.WriteLine("还没开始遍历");
foreach (var n in query) Console.WriteLine(n); // ⚡ 到这里才真正执行csharp- LINQ 查询默认延迟执行:定义时不做事,遍历时才计算
- 每次遍历都重新计算,必要时用
ToList()/ToArray()固化结果:
var list = query.ToList(); // 立即执行并缓存csharp5. LINQ 家族#
| 类型 | 命名空间 | 数据源 |
|---|---|---|
| LINQ to Objects | System.Linq | 内存集合(本文内容) |
| LINQ to Entities(EF Core) | Microsoft.EntityFrameworkCore | 数据库(转成 SQL 执行) |
| LINQ to XML | System.Xml.Linq | XML(XDocument) |
⚠️ 注意区别:操作内存集合的 LINQ 在 C# 内存中执行;EF Core 的 LINQ 会被翻译成 SQL,部分方法(如自定义方法调用)无法翻译,会报 “could not be translated” 错误。