一、LINQ 的核心概念
-
什么是 LINQ?
-
一种将查询能力直接集成到编程语言中的技术
-
提供统一的语法查询多种数据源:
-
内存对象集合(List,Array)
-
数据库(SQL Server,Oracle)
-
XML 文档
-
JSON 数据
-
实体数据模型
-
-
编译时类型检查,避免运行时错误
-
-
核心组件:
=LINQ=
LINQ to Objects
LINQ to SQL
LINQ to XML
LINQ to Entities
LINQ to DataSet
二、LINQ 的两种语法形式
1. 查询表达式语法(类似 SQL)
csharp
// 从集合中查询大于 10 的偶数,按降序排列 var result = from num in numbers where num > 10 && num % 2 == 0 orderby num descending select num * 2; // 将数值翻倍
2. 方法链语法(Lambda 表达式)
csharp
// 等效的链式方法调用
var result = numbers
.Where(num => num > 10 && num % 2 == 0)
.OrderByDescending(num => num)
.Select(num => num * 2);
三、LINQ 的核心操作符
| 类别 | 操作符 | 功能描述 | 示例 |
|---|---|---|---|
| 过滤 | Where | 条件过滤 | .Where(p => p.Price > 100) |
| 投影 | Select / SelectMany | 选择/展平数据 | .Select(p => p.Name) |
| 排序 | OrderBy / ThenBy | 升序排序 | .OrderBy(p => p.Price) |
| OrderByDescending | 降序排序 | .OrderByDescending(p => p.Price) | |
| 分组 | GroupBy | 数据分组 | .GroupBy(p => p.Category) |
| 连接 | Join | 内连接 | .Join(.. on .. equals ..) |
| GroupJoin | 分组连接 | ||
| 聚合 | Count / Sum / Average | 计数/求和/平均值 | .Count(), .Sum(p => p.Price) |
| Min / Max | 最小值/最大值 | .Min(p => p.Age) | |
| 分区 | Take / Skip | 获取前N项/跳过前N项 | .Take(5), .Skip(10) |
| TakeWhile / SkipWhile | 条件获取/跳过 | ||
| 集合 | Distinct | 去重 | .Distinct() |
| Union / Intersect | 并集/交集 | list1.Union(list2) | |
| 元素 | First / Last | 获取第一个/最后一个元素 | .First(), .Last() |
| FirstOrDefault | 安全获取第一个元素 | .FirstOrDefault() | |
| 转换 | ToArray / ToList | 转换为数组/列表 | .ToList() |
| ToDictionary | 转换为字典 | .ToDictionary(p => p.Id) | |
| 生成 | Range / Repeat | 生成数字序列/重复值序列 | Enumerable.Range(1, 10) |
四、实际应用示例
示例 1:查询产品信息
csharp
复制
下载
class Product
{
public int ID { get; set; }
public string Name { get; set; }
public string Category { get; set; }
public decimal Price { get; set; }
}
List<Product> products = new List<Product>
{
new Product { ID = 1, Name = "笔记本电脑", Category = "电子", Price = 5999 },
new Product { ID = 2, Name = "智能手机", Category = "电子", Price = 3999 },
new Product { ID = 3, Name = "咖啡机", Category = "家电", Price = 899 }
};
// 查询所有电子类产品,按价格降序排列
var electronics = from p in products
where p.Category == "电子"
orderby p.Price descending
select new {
p.Name,
DiscountedPrice = p.Price * 0.9m // 打9折
};
// 等效方法语法
var electronicsMethod = products
.Where(p => p.Category == "电子")
.OrderByDescending(p => p.Price)
.Select(p => new {
p.Name,
DiscountedPrice = p.Price * 0.9m
});
示例 2:分组统计
csharp
复制
下载
// 按类别分组并计算每类产品的平均价格
var categoryStats = from p in products
group p by p.Category into g
select new {
Category = g.Key,
Count = g.Count(),
AvgPrice = g.Average(p => p.Price)
};
// 输出:电子类:2件产品,平均¥4999.00
foreach (var stat in categoryStats)
{
Console.WriteLine($"{stat.Category}类:{stat.Count}件产品,平均{stat.AvgPrice:C}");
}
五、LINQ 的核心优势
-
声明式编程:
-
描述"要什么"而不是"如何获取"
-
提高代码可读性
csharp
复制
下载
// 传统命令式 List<string> results = new List<string>(); foreach (var p in products) { if (p.Price > 1000) results.Add(p.Name.ToUpper()); } // LINQ 声明式 var results = products .Where(p => p.Price > 1000) .Select(p => p.Name.ToUpper()); -
-
统一查询模型:
-
相同的语法查询不同数据源
-
降低学习曲线
-
-
延迟执行(Deferred Execution):
-
查询定义时不立即执行
-
实际使用时才执行(如遍历结果时)
csharp
复制
下载
var query = products.Where(p => p.Price > 1000); // 未执行 // 添加新产品 products.Add(new Product { Price = 2000 }); foreach (var p in query) // 此时执行,包含新产品 { Console.WriteLine(p.Name); } -
-
强类型检查:
-
编译时检查查询语法
-
避免运行时错误
-
六、LINQ 的实际应用场景
-
数据库访问(LINQ to SQL):
csharp
复制
下载
using (var db = new DataContext()) { var customers = from c in db.Customers where c.City == "北京" orderby c.LastName select c; } -
XML 处理(LINQ to XML):
csharp
复制
下载
XDocument doc = XDocument.Load("data.xml"); var names = from element in doc.Descendants("Employee") where (int)element.Element("Age") > 30 select element.Element("Name").Value; -
内存集合处理:
csharp
复制
下载
// 找出所有长度大于5的文件路径 var longFiles = Directory.GetFiles("C:\\", "*", SearchOption.AllDirectories) .Where(file => new FileInfo(file).Length > 5 * 1024 * 1024) .OrderBy(file => file.Length);
七、性能注意事项
-
立即执行 vs 延迟执行:
-
使用
ToList()、ToArray()强制立即执行 -
多次使用时缓存结果
-
-
复杂查询优化:
csharp
复制
下载
// 低效:多次访问数据库 for (int i = 0; i < ids.Length; i++) { var product = db.Products.First(p => p.ID == ids[i]); } // 高效:单次查询 var products = db.Products.Where(p => ids.Contains(p.ID)).ToList(); -
PLINQ(并行 LINQ):
csharp
复制
下载
// 自动并行处理大数据集 var results = data.AsParallel() .Where(item => ComplexCheck(item)) .ToList();
八、学习资源推荐
-
官方文档:
-
交互式教程:
-
LINQ Pad - 即时测试 LINQ 查询
-
-
经典书籍:
-
《C# in Depth》(Jon Skeet)
-
《LINQ Pocket Reference》
-
LINQ 彻底改变了 .NET 开发者的数据处理方式,将查询能力提升为编程语言的一等公民。掌握 LINQ 不仅能提高开发效率,还能写出更简洁、更具表达力的代码。
namespace LINQ用法
{
internal class Program
{
static void Main(string[] args)
{
// 示例1:基本Select用法 - 创建匿名对象
Console.WriteLine("===== 示例1:Select创建匿名对象 =====");
// 创建简单整数列表
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
// 使用Select和匿名对象创建新序列
var squaredNumbers = numbers.Select(n => new
{
Original = n, // 保留原始值
Squared = n * n, // 计算平方值
IsEven = n % 2 == 0 // 判断是否为偶数
});
// 输出结果
foreach (var item in squaredNumbers)
{
Console.WriteLine($"原始值: {item.Original}, " +
$"平方: {item.Squared}, " +
$"偶数? {item.IsEven}");
}
Console.WriteLine("\n");
// 示例2:Zip和匿名对象组合数据
Console.WriteLine("===== 示例2:Zip合并序列 =====");
// 创建两个相关序列
List<string> fruits = new List<string> { "苹果", "香蕉", "橙子" };
List<double> prices = new List<double> { 5.99, 3.49, 4.25 };
List<int> stock = new List<int> { 10, 15, 8 }; // 库存数量
// 使用Zip合并水果和价格
var fruitPricePairs = fruits.Zip(prices, (fruit, price) => new
{
FruitName = fruit,
Price = price
});
Console.WriteLine("合并水果和价格:");
foreach (var item in fruitPricePairs)
{
Console.WriteLine($"水果: {item.FruitName}, 价格: {item.Price:C}");
}
Console.WriteLine("\n");
// 示例3:多层Zip嵌套(类似你的场景)
Console.WriteLine("===== 示例3:多层Zip嵌套 =====");
// 第一步:合并水果和价格
var fruitPrice = fruits.Zip(prices, (f, p) => new
{
Name = f,
Price = p
});
// 第二步:将上一步结果与库存合并
var fullInfo = fruitPrice.Zip(stock, (fp, s) => new
{
Fruit = fp.Name, // 从第一层对象获取水果名
Price = fp.Price, // 从第一层对象获取价格
Stock = s // 添加库存信息
});
Console.WriteLine("完整水果信息:");
foreach (var item in fullInfo)
{
Console.WriteLine($"名称: {item.Fruit}, " +
$"价格: {item.Price:C}, " +
$"库存: {item.Stock}件");
}
Console.WriteLine("\n");
// 示例4:链式调用(更紧凑的写法)
Console.WriteLine("===== 示例4:链式调用 =====");
var chainedResult = fruits
.Zip(prices, (f, p) => new { Fruit = f, Price = p })
.Zip(stock, (fp, s) => new
{
Name = fp.Fruit,
Cost = fp.Price,
Inventory = s,
TotalValue = fp.Price * s // 计算总价值
});
Console.WriteLine("水果库存价值:");
foreach (var item in chainedResult)
{
Console.WriteLine($"{item.Name}: " +
$"单价 {item.Cost:C}, " +
$"库存 {item.Inventory}, " +
$"总值 {item.TotalValue:C}");
}
}
}
}

1143

被折叠的 条评论
为什么被折叠?



