You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用C# LINQ Intersect合并多列表为去重列表却得到空列表,求排查

问题分析与解决方案

一、核心逻辑错误:误用Intersect而非Union

你的代码初始combinedMaterialList是空列表,而Intersect的作用是求两个集合的交集——空集合和任何集合的交集必然是空,所以第一次循环后结果就为空,后续循环自然一直返回空列表。

你实际需要的是合并所有列表并去重,这应该用Union(并集操作,自动去重),或者先把所有元素合并再调用Distinct。

二、相等性判断不一致:Equals与GetHashCode逻辑不匹配

LINQ的集合操作(如Intersect/Union/Distinct)依赖对象的相等性判断,要求Equals和GetHashCode的逻辑必须完全一致:

  • 你的Equals方法仅通过ExternalId判断两个Material是否相等
  • 但GetHashCode却结合了Id、ExternalId、Name、Quantity多个属性

这种不一致会导致:即使两个对象的ExternalId相同(Equals返回true),只要其他属性不同,它们的哈希值就不同,LINQ会直接判定为不同对象,不会触发Equals比较,最终去重逻辑失效。


修正后的代码

1. 合并去重逻辑(二选一)

方式一:循环用Union合并

List<Material> combinedMaterialList = new List<Material>();
foreach (var project in projects)
{
    combinedMaterialList = combinedMaterialList.Union(project.Materials).ToList();
}

方式二:SelectMany一次性合并(更高效)

List<Material> combinedMaterialList = projects
    .SelectMany(project => project.Materials)
    .Distinct()
    .ToList();

2. 修正Material类的相等性实现

必须让Equals和GetHashCode逻辑一致,同时重写object基类的Equals方法:

public int Id { get; set; }
public int ExternalId { get; set; }
public string? Name { get; set; }
public decimal Quantity { get; set; }

public bool Equals(Material? other)
{
    if (other is null)
        return false;
    if (ReferenceEquals(this, other))
        return true;
    // 仅通过ExternalId判断相等,和GetHashCode逻辑对齐
    return GetType() == other.GetType() && ExternalId == other.ExternalId;
}

// 重写object的Equals,确保LINQ能正确调用
public override bool Equals(object? obj)
{
    return Equals(obj as Material);
}

public override int GetHashCode()
{
    // 仅基于ExternalId计算哈希值
    return ExternalId.GetHashCode();
}

内容的提问来源于stack exchange,提问作者Blake Rivell

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 09:31:43