C# LINQ:查询语法与方法语法的使用
LINQ(Language Integrated Query)是 C# 中用于操作数据集合的强大工具。它允许你像写 SQL 一样从数组、列表、数据库等数据源中筛选、排序和转换数据。LINQ 提供两种写法:查询语法(Query Syntax)和方法语法(Method Syntax)。两者功能完全等价,只是写法不同。下面直接教你如何使用。
查询语法:像写 SQL 一样查数据
查询语法看起来更接近 SQL,适合复杂查询或多步骤筛选。
-
声明一个数据源。例如,创建一个整数列表:
var numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; -
用
from ... where ... select写查询。例如,找出所有大于 5 的偶数:var result = from n in numbers where n > 5 && n % 2 == 0 select n; -
执行查询并输出结果。注意:LINQ 查询是“延迟执行”的,只有在遍历时才真正运行:
foreach (var item in result) { Console.WriteLine(item); // 输出 6, 8, 10 } -
支持多条件排序。例如,先按长度降序,再按字母升序(适用于字符串):
var words = new List<string> { "apple", "fig", "banana", "cherry" }; var sorted = from w in words orderby w.Length descending, w ascending select w; -
可以投影新对象。例如,把每个数字变成匿名对象:
var info = from n in numbers where n % 2 == 0 select new { Value = n, IsEven = true };
方法语法:用链式调用操作数据
方法语法使用扩展方法(如 Where、Select、OrderBy),适合简单操作或函数式风格。
-
对同一数据源使用方法链。上面“大于 5 的偶数”例子改写为:
var result = numbers.Where(n => n > 5).Where(n => n % 2 == 0);或合并条件:
var result = numbers.Where(n => n > 5 && n % 2 == 0); -
常用方法直接调用:
- 筛选:
Where(condition) - 投影:
Select(transformer) - 排序:
OrderBy(key)或OrderByDescending(key) - 去重:
Distinct() - 取前 N 项:
Take(n) - 跳过前 N 项:
Skip(n)
- 筛选:
-
组合多个操作。例如,取前 3 个大于 3 的偶数并平方:
var squares = numbers .Where(n => n > 3 && n % 2 == 0) .Take(3) .Select(n => n * n); -
立即执行的方法。有些方法会立刻计算结果(而非延迟):
ToList():转成List<T>ToArray():转成数组Count():返回元素数量First()/FirstOrDefault():取第一个元素
示例:
var list = numbers.Where(n => n < 5).ToList();
查询语法 vs 方法语法:怎么选?
两种语法可互相转换,选择取决于场景和个人习惯。以下是对比:
| 特性 | 查询语法 | 方法语法 |
|---|---|---|
| 可读性(复杂查询) | 更高(类似 SQL) | 较低(嵌套 lambda) |
| 可读性(简单操作) | 略显冗长 | 更简洁 |
| 支持的操作 | 大部分常见操作 | 全部 LINQ 操作(如 Aggregate, Zip) |
| 学习曲线 | 对 SQL 用户友好 | 对函数式编程用户友好 |
| 调试便利性 | 难以单步调试中间步骤 | 可拆分为多行,方便调试 |
关键结论:复杂多表关联或嵌套查询用查询语法;简单过滤、转换或需要调用特殊方法时用方法语法。
实战:两种语法混合使用
实际开发中,经常混合使用两种语法以发挥各自优势。
-
先用查询语法做主体筛选:
var query = from p in products where p.Price < 100 orderby p.Name select p; -
再用方法语法追加操作:
var finalList = query.Take(10).ToList(); -
或者反过来:先用方法语法预处理,再用查询语法细化:
var cheapProducts = products.Where(p => p.Price < 50); var result = from p in cheapProducts where p.Category == "Electronics" select p.Name.ToUpper();
注意事项与最佳实践
-
避免重复执行。LINQ 查询每次遍历都会重新计算。如果多次使用结果,调用
ToList()或ToArray()缓存:var cached = data.Where(x => x.IsValid).ToList(); // 执行一次 -
不要在循环中定义 LINQ 查询。这会导致每次迭代都重新构建表达式树,影响性能。
-
优先使用方法语法调用非查询操作。例如,
Count()、Any()、Sum()等聚合方法在方法语法中更自然:bool hasExpensive = products.Any(p => p.Price > 1000); -
命名清晰的变量。无论哪种语法,变量名应反映其含义:
var affordablePhones = from p in products where p.Category == "Phone" && p.Price < 500 select p; -
理解延迟执行。以下代码不会立即运行查询:
var q = numbers.Where(n => n > 0); // 此时未执行 numbers.Add(999); // 修改原列表 var list = q.ToList(); // 此时执行,包含 999
立即执行可避免此类副作用。

暂无评论,快来抢沙发吧!