首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >LINQ的魔幻与禁忌:5个让你既爱又恨的"骚操作

LINQ的魔幻与禁忌:5个让你既爱又恨的"骚操作

作者头像
郑子铭
发布2025-07-24 10:10:54
发布2025-07-24 10:10:54
9600
代码可运行
举报
运行总次数:0
代码可运行

LINQ的使用,往往在"巧妙"与"邪恶"之间只有一线之隔。

我曾深刻领悟这一点——在一次代码评审中,我自信满满地展示了一段自认为堪称艺术品的LINQ代码,结果看着资深开发者的表情逐渐扭曲。"这……确实能跑,"他缓缓说道,"但今晚我可能会因为这段代码失眠。"

LINQ不仅是一种工具,更是一种武器。 而任何武器,既能行善,也能作恶。

以下是我用过的5个最具争议的LINQ技巧(后来恨不得从未写过):


1. 副作用手枪(在Select中执行代码)

代码语言:javascript
代码运行次数:0
运行
复制
var processedOrders = orders.Select(order => {  
    order.Total = ApplyRegionalTax(order.Total);  
    AuditLog.Write($"Processed: {order.Id}");  
    return order;  
}).ToList();

为何邪恶? LINQ本应只用于查询,而非执行副作用。Select 应该是纯函数——仅处理数据,而非记录日志或修改状态。

正确做法:先处理集合,再投影

代码语言:javascript
代码运行次数:0
运行
复制
foreach (var order in orders)  
{  
    order.Total = ApplyRegionalTax(order.Total);  
    AuditLog.Write($"Processed: {order.Id}");  
}  
var processedOrders = orders.ToList();

2. ToList() 诱饵陷阱(强制提前执行)

代码语言:javascript
代码运行次数:0
运行
复制
var results = dbContext.Products  
    .Where(p => p.IsActive)  
    .ToList()  // ← 邪恶的天才时刻  
    .Select(p => ExpensiveTransformation(p));

为何邪恶? ToList() 会先将所有活跃产品加载到内存,再执行转换。如果数据量大,性能直接爆炸。

正确做法:让数据库先过滤

代码语言:javascript
代码运行次数:0
运行
复制
var results = dbContext.Products  
    .Where(p => p.IsActive)  
    .AsEnumerable()  // 在数据库过滤后切换至LINQ-to-Objects  
    .Select(p => ExpensiveTransformation(p));

3. SelectMany 地雷(嵌套循环失控)

代码语言:javascript
代码运行次数:0
运行
复制
var allPermissions = users  
    .SelectMany(u => u.Roles)  
    .SelectMany(r => r.Permissions)  
    .Distinct();

为何邪恶? 如果 UsersRoles 数据量大,这会引发笛卡尔积爆炸。更糟的是,由于延迟执行,爆炸可能发生在远离代码的地方。

正确做法:尽早物化或重构查询

代码语言:javascript
代码运行次数:0
运行
复制
var roleIds = users.SelectMany(u => u.Roles).Select(r => r.Id).Distinct();  
var permissions = dbContext.Permissions.Where(p => roleIds.Contains(p.RoleId));

4. Aggregate 陷阱(隐藏的复杂度炸弹)

代码语言:javascript
代码运行次数:0
运行
复制
var csvLine = orders.Aggregate("", (acc, order) => $"{acc},{order.Id}");

为何邪恶? Aggregate可读性黑洞,且会生成N次字符串分配(GC压力警告⚠️)。

正确做法:像文明人一样用 string.Join

代码语言:javascript
代码运行次数:0
运行
复制
var csvLine = string.Join(",", orders.Select(o => o.Id));

5. 空条件运算符的混乱(?. 在LINQ中的滥用)

代码语言:javascript
代码运行次数:0
运行
复制
var customerNames = orders  
    .Select(o => o.Customer?.Name ?? "Ghost Customer")  
    .ToList();

为何邪恶? LINQ中的空检查会掩盖数据问题。如果 Customernull,这是否是Bug?查询默默掩盖了它。

正确做法:快速失败或先过滤

代码语言:javascript
代码运行次数:0
运行
复制
var validOrders = orders.Where(o => o.Customer != null);  
var customerNames = validOrders.Select(o => o.Customer.Name);

"能力越大,责任越大。" LINQ赋予我们强大的表达能力,但滥用会导致代码变得晦涩、低效,甚至埋下隐藏Bug。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-07-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DotNet NB 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 副作用手枪(在Select中执行代码)
  • 2. ToList() 诱饵陷阱(强制提前执行)
  • 3. SelectMany 地雷(嵌套循环失控)
  • 4. Aggregate 陷阱(隐藏的复杂度炸弹)
  • 5. 空条件运算符的混乱(?. 在LINQ中的滥用)
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档