显示页面讨论反向链接回到顶部 本页面只读。您可以查看源文件,但不能更改它。如果您觉得这是系统错误,请联系管理员。 ====== C# LINQ (Language Integrated Query) 详解 ====== **LINQ** (语言集成查询) 是 C# 中的一组功能,它允许你使用统一的语法来查询不同的数据源(如内存集合、数据库、XML 等)。 它的核心优势在于: * **一致性**:无论数据源是 List 还是 SQL 数据库,查询语法基本一致。 * **强类型**:编译时检查错误,而不是运行时才发现 SQL 拼写错误。 * **可读性**:代码更简洁,意图更明确。 ===== 1. 准备数据 (Data Source) ===== 为了演示,我们先定义一个简单的 `Student` 类和一些测试数据。 <code csharp> using System; using System.Collections.Generic; using System.Linq; public class Student { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } public string ClassName { get; set; } } // 模拟数据源 var students = new List<Student> { new Student { Id = 1, Name = "Alice", Age = 22, ClassName = "A" }, new Student { Id = 2, Name = "Bob", Age = 19, ClassName = "B" }, new Student { Id = 3, Name = "Charlie", Age = 24, ClassName = "A" }, new Student { Id = 4, Name = "David", Age = 20, ClassName = "B" }, new Student { Id = 5, Name = "Eve", Age = 22, ClassName = "A" } }; </code> ===== 2. 两种语法风格 (Syntax Styles) ===== LINQ 有两种写法,它们在编译后是等价的。 ==== 2.1 查询语法 (Query Syntax) ==== 看起来像 SQL,适合复杂的连接(Join)和分组操作。 <code csharp> // 查找所有年龄大于 20 岁的学生 var query = from s in students where s.Age > 20 select s; </code> ==== 2.2 方法语法 (Method Syntax) ==== 使用 Lambda 表达式,是现代 C# 开发中最常用的方式,支持所有 LINQ 操作符。 <code csharp> // 查找所有年龄大于 20 岁的学生 var query = students.Where(s => s.Age > 20); </code> ===== 3. 常用操作符 (Common Operators) ===== 以下示例主要使用**方法语法**。 ==== 3.1 筛选 (Filtering) - Where ==== <code csharp> // 找出班级是 "A" 的学生 var classAStudents = students.Where(s => s.ClassName == "A"); </code> ==== 3.2 投影 (Projection) - Select ==== 用于转换数据,例如只取某一列,或者构造新的对象。 <code csharp> // 只获取所有学生的姓名 (返回 List<string>) var names = students.Select(s => s.Name); // 构造匿名对象 (只包含 ID 和 姓名) var simpleList = students.Select(s => new { s.Id, s.Name }); </code> ==== 3.3 排序 (Sorting) - OrderBy / ThenBy ==== <code csharp> // 按年龄升序排序 var sortedByAge = students.OrderBy(s => s.Age); // 按年龄降序,如果年龄相同则按名字升序 var sortedComplex = students.OrderByDescending(s => s.Age) .ThenBy(s => s.Name); </code> ==== 3.4 分页 (Partitioning) - Skip / Take ==== 常用于 Web 开发中的分页功能。 <code csharp> // 跳过前 2 个,取接下来的 2 个 (获取第 3、4 名学生) var page2 = students.Skip(2).Take(2); </code> ==== 3.5 聚合 (Aggregation) ==== 用于计算统计数据。 <code csharp> int count = students.Count(); // 总数 int maxAge = students.Max(s => s.Age); // 最大年龄 double avgAge = students.Average(s => s.Age); // 平均年龄 int sumAge = students.Sum(s => s.Age); // 年龄总和 </code> ==== 3.6 元素获取 (Element Operators) ==== 获取单个元素,注意处理空值情况。 <code csharp> // 获取第一个元素,如果没有则抛出异常 var first = students.First(s => s.Age > 20); // 获取第一个元素,如果没有则返回 null (推荐) var firstSafe = students.FirstOrDefault(s => s.Age > 100); // 检查是否包含满足条件的元素 (返回 bool) bool hasUnderage = students.Any(s => s.Age < 18); // 检查是否所有元素都满足条件 (返回 bool) bool allAdults = students.All(s => s.Age >= 18); </code> ===== 4. 高级操作 (Advanced) ===== ==== 4.1 分组 (GroupBy) ==== 将数据按某个键归类。 <code csharp> // 按班级分组 var grouped = students.GroupBy(s => s.ClassName); foreach (var group in grouped) { Console.WriteLine($"班级: {group.Key}"); // Key 是 ClassName foreach (var student in group) { Console.WriteLine($" - {student.Name}"); } } </code> ==== 4.2 集合操作 ==== <code csharp> var list1 = new List<int> { 1, 2, 3 }; var list2 = new List<int> { 3, 4, 5 }; var union = list1.Union(list2); // 并集: 1, 2, 3, 4, 5 var intersect = list1.Intersect(list2); // 交集: 3 var except = list1.Except(list2); // 差集 (list1 - list2): 1, 2 var distinct = list1.Concat(list1).Distinct(); // 去重 </code> ===== 5. 延迟执行 vs 立即执行 (Important!) ===== 这是 LINQ 中最重要的概念之一。 * **延迟执行 (Deferred Execution)**: * 大多数 LINQ 操作符(如 `Where`, `Select`, `OrderBy`)**不会立即查询数据**。 * 它们只是构建了一个查询计划。 * 只有当你遍历结果(`foreach`)时,查询才会真正执行。 * **立即执行 (Immediate Execution)**: * 某些方法会强制立即执行查询并把结果存入内存。 * 常见方法:`ToList()`, `ToArray()`, `Count()`, `First()`. <code csharp> // 1. 定义查询 (此时还没运行) var query = students.Where(s => s.Age < 20); // 2. 修改数据源 (注意:我们在定义查询之后修改了数据) students.Add(new Student { Name = "NewKid", Age = 15 }); // 3. 执行查询 (foreach 或 ToList) // 结果会包含 "NewKid",因为查询是在这一行才真正执行的! var result = query.ToList(); </code> **最佳实践**: - 如果你需要多次遍历同一个查询结果,请先调用 `.ToList()` 缓存结果,否则每次遍历都会重新执行一遍查询逻辑(如果连的是数据库,这会造成性能浪费)。 ===== 6. 总结 ===== | 操作类型 | 常用方法 | | **筛选** | ''Where'', ''OfType'' | | **投影** | ''Select'', ''SelectMany'' | | **排序** | ''OrderBy'', ''OrderByDescending'', ''ThenBy'' | | **聚合** | ''Count'', ''Sum'', ''Min'', ''Max'', ''Average'' | | **量词** | ''Any'', ''All'', ''Contains'' | | **分区** | ''Skip'', ''Take'' | | **转换** | ''ToList'', ''ToArray'', ''ToDictionary'' | 登录 Detach Close 该主题尚不存在 您访问的页面并不存在。如果允许,您可以使用创建该页面按钮来创建它。 csharp/linq.txt 最后更改: 2025/11/26 09:48由 张叶安 登录