在 c# 中使用 linq 相交和相等将多个列表组合成一个不同的列表

问题描述 投票:0回答:1

我需要使用 linq 和 intersect 将多个列表合并为一个合并的不同列表。我最终得到一个空列表。知道我可能做错了什么吗?

这是我的代码:

// 合并所有不同的材质项

List<Material> combinedMaterialList = new List<Material>();

foreach (var project in projects)
{
     combinedMaterialList = combinedMaterialList.Intersect(project.Materials).ToList();
}

这是 Material 类,因为相交将基于平等工作:

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

public bool Equals(Material m)
{
    if (m is null)
    {
        return false;
    }

    // Optimization for a common success case.
    if (Object.ReferenceEquals(this, m))
    {
        return true;
    }

    // If run-time types are not exactly the same, return false.
    if (this.GetType() != m.GetType())
    {
        return false;
    }

    // Return true if the fields match.
    // Note that the base class is not invoked because it is
    // System.Object, which defines Equals as reference equality.
    return (ExternalId == m.ExternalId);
}

    public override int GetHashCode()
    {
        return HashCode.Combine(Id, ExternalId, Name, Quantity);
    }
c# linq equality
1个回答
1
投票

首先确保您已经为

Equals
类实现了
GetHashCode
Material

public class Material: IEquatable<Material> {
  ...
  
  public bool Equals(Material other) {
    if (ReferenceEquals(this, other))
      return true;
    if (other is null)
      return false;

    return ExternalId == other.ExternalId;
  }

  public override bool Equals(object o) => o is Material other && Equals(other);

  // Note, that GetHashCode must not be more restrictive than Equals:
  // If Equals compare ExternalId only, so must do GetHashCode
  public override int GetHashCode() => ExternalId; 
}

实施

Equals
后,您应该选择以下方法之一:

  • Intersect
    两个列表中的所有项目
  • Union
    至少其中一个列表中的所有项目
  • Except
    :第一个列表中的所有项目,但不在第二个列表中
在任何情况下

都会删除重复项。 例如:

// Since combinedMaterialList is empty, // Intersect or Except have no meaning here: the result will be // an empty list. The only reasonable choice is Union List<Material> combinedMaterialList = new List<Material>(); // Combined list contains item from all project.Materials, // duplicates removed foreach (var project in projects) { combinedMaterialList = combinedMaterialList .Union(project.Materials) .ToList(); }

© www.soinside.com 2019 - 2024. All rights reserved.