C#中判断购物车商品与历史订单商品是否存在交集的问题
问题:判断购物车商品是否存在于历史订单中
购物车中有若干商品,客户曾订购过其中某一件。已通过GetOrders()方法获取客户的历史订单列表,将购物车商品传入ProductFound方法,需判断购物车商品与订单中的OrderItems是否存在匹配。
原始错误代码及问题
最初编写的代码如下,已知存在匹配商品但始终返回false:
public bool ProductFound(IReadOnlyCollection<OrderItems> items) { var orders = GetOrders(); foreach (var order in orders) { if (items.Intersect(order.OrderItems).Any()) { return true; } } return false; }
尝试通过order.OrderItems.ProductId匹配ID时出现类型转换错误,修改为嵌套循环后仍未解决:
public bool ProductFound(IReadOnlyCollection<OrderItems> items) { var orders = GetOrders(); foreach (var order in orders) { foreach (var i in orders.OrderItems) { if (items.Contains(i)) { return true; } } } return false; }
问题原因分析
Intersect/Contains失效原因:默认情况下,这些方法使用引用相等判断,只有当两个对象是内存中的同一实例时才会判定相等。即使两个OrderItems对象的ProductId相同,只要是不同实例,就会被判定为不相等。- 嵌套循环的错误:代码中错误访问了
orders.OrderItems,而不是当前遍历的order.OrderItems,导致逻辑错误。
正确实现方式
方式一:通过唯一标识(如ProductId)匹配(推荐)
无需修改OrderItems类,直接基于商品唯一ID判断,性能和可靠性都更高:
public bool ProductFound(IReadOnlyCollection<OrderItems> cartItems) { var orders = GetOrders(); // 提取购物车所有商品ID存入HashSet,提升查询效率 var cartProductIds = cartItems.Select(item => item.ProductId).ToHashSet(); foreach (var order in orders) { // 检查当前订单是否有商品ID存在于购物车ID集合中 if (order.OrderItems.Any(orderItem => cartProductIds.Contains(orderItem.ProductId))) { return true; } } return false; }
方式二:重写OrderItems的相等判断方法
如果需要基于对象内容进行相等判断,在OrderItems类中重写Equals和GetHashCode:
public class OrderItems { public int ProductId { get; set; } // 其他属性... public override bool Equals(object obj) { // 先判断是否为同一类型实例 if (!(obj is OrderItems otherItem)) return false; // 基于ProductId判断相等 return ProductId == otherItem.ProductId; } public override int GetHashCode() { // 基于ProductId生成哈希码 return HashCode.Combine(ProductId); } }
修改后,最初的Intersect代码即可正常工作:
public bool ProductFound(IReadOnlyCollection<OrderItems> items) { var orders = GetOrders(); foreach (var order in orders) { if (items.Intersect(order.OrderItems).Any()) { return true; } } return false; }
方式三:使用自定义相等比较器
若无法修改OrderItems类,可创建自定义比较器实现相等判断:
public class OrderItemEqualityComparer : IEqualityComparer<OrderItems> { public bool Equals(OrderItems x, OrderItems y) { if (x == null || y == null) return x == y; return x.ProductId == y.ProductId; } public int GetHashCode(OrderItems obj) { return obj.ProductId.GetHashCode(); } }
在Intersect方法中传入该比较器即可:
public bool ProductFound(IReadOnlyCollection<OrderItems> items) { var orders = GetOrders(); var equalityComparer = new OrderItemEqualityComparer(); foreach (var order in orders) { if (items.Intersect(order.OrderItems, equalityComparer).Any()) { return true; } } return false; }
内容的提问来源于stack exchange,提问作者KeithViking
相关产品推荐
相关产品推荐

