如何用LINQ替代foreach获取多结果且不创建新集合?
问题分析
原foreach循环的核心问题是:第一次进入循环就执行return,函数直接返回第一个匹配的结果集合,后续的orderComplimentaryUtility完全没机会遍历,自然拿不到所有符合条件的OrderItem。
正确的LINQ实现方式
以下几种实现都利用LINQ延迟执行特性,不会在方法内创建新集合,完全满足你的需求:
方式一:先提取目标ID再筛选(可读性优先)
public static IEnumerable<OrderItem> WhichUtilitiesAreAlreadyInBasket( this IEnumerable<OrderComplimentaryUtility.OrderComplimentaryUtility> orderComplimentaryUtilities, Order basket) { if (basket == null || orderComplimentaryUtilities == null) { return Enumerable.Empty<OrderItem>(); } // 延迟提取所有需要匹配的ID,不会立即生成集合 var targetIds = orderComplimentaryUtilities.Select(u => u.Id); // 筛选basket中ID在目标集合内的Item return basket.Items.Where(item => targetIds.Contains(item.Id)); }
方式二:用SelectMany合并所有匹配结果
public static IEnumerable<OrderItem> WhichUtilitiesAreAlreadyInBasket( this IEnumerable<OrderComplimentaryUtility.OrderComplimentaryUtility> orderComplimentaryUtilities, Order basket) { if (basket == null || orderComplimentaryUtilities == null) { return Enumerable.Empty<OrderItem>(); } // 对每个Utility找到匹配的Item,再合并所有结果 return orderComplimentaryUtilities.SelectMany(u => basket.Items.Where(item => item.Id == u.Id)); }
方式三:用Join关联集合(性能优先)
数据量较大时,Join的效率比多次Contains更高:
public static IEnumerable<OrderItem> WhichUtilitiesAreAlreadyInBasket( this IEnumerable<OrderComplimentaryUtility.OrderComplimentaryUtility> orderComplimentaryUtilities, Order basket) { if (basket == null || orderComplimentaryUtilities == null) { return Enumerable.Empty<OrderItem>(); } // 按ID关联两个集合,返回匹配的OrderItem return orderComplimentaryUtilities.Join( basket.Items, u => u.Id, item => item.Id, (u, item) => item); }
补充说明
你之前尝试的SelectMany写法逻辑错误:item.Id == orderComplimentaryUtilities.Where(o => o.Id)是布尔值和集合的无效比较,正确的SelectMany需要传入一个返回集合的委托,参考方式二即可。
内容的提问来源于stack exchange,提问作者Nodessa
相关产品推荐
相关产品推荐

