【问题标题】:List.Contains doesn't work properlyList.Contains 无法正常工作
【发布时间】:2013-02-07 20:40:41
【问题描述】:

我有一个包含对象的列表,但这些对象在列表中并不是唯一的。我写了这段代码以使它们在另一个列表中独一无二:

 foreach (CategoryProductsResult categoryProductsResult in categoryProductsResults.Where(categoryProductsResult => !resultSet.Contains(categoryProductsResult)))
 {
    resultSet.Add(categoryProductsResult);
 }

但最终结果集与 categoryProductsResults 相同。

categoryProductsResult 的第二行:

结果集第一行:

如您所见,resultSet 的第一行和 categoryProductsResult 的第二行是一样的,但是它将第二行添加到 resultSet。

你有什么建议吗?

【问题讨论】:

  • 告诉我们你在哪里覆盖.equals()

标签: c# linq list


【解决方案1】:

Contains 使用默认比较器来比较引用,因为您的类不会覆盖 EqualsGetHashCode

class CategoryProductsResult
{
    public string Name { get; set; }
    // ...

    public override bool  Equals(object obj)
    {
        if(obj == null)return false;
        CategoryProductsResult other = obj as CategoryProductsResult;
        if(other == null)return false;
        return other.Name == this.Name;
    }

    public override int  GetHashCode()
    {
         return Name.GetHashCode();
    }
}

现在您可以简单地使用:

resultSet = categoryProductsResults.Distinct().ToList();

【讨论】:

    【解决方案2】:

    List 使用 EqualityComparer.Default 返回的比较器,并根据文档:

    Default 属性检查类型 T 是否实现 System.IEquatable(Of T) 接口,如果是,则返回一个 使用该实现的 EqualityComparer(Of T)。否则,它 返回使用覆盖的 EqualityComparer(Of T) T 提供的 Object.Equals 和 Object.GetHashCode。

    因此,您可以在您的自定义类上实现 IEquatable,或者覆盖 Equals(和 GetHashCode)方法,通过您需要的属性进行比较。或者,您可以使用 linq:

    bool contains = list.Any(i => i.Id == obj.Id);

    【讨论】:

      【解决方案3】:

      每个categoryProductsResult 彼此不同。就像您可以看到here 一样。如果您想要一个更简单的并且 ProductId 是您的唯一标识符。只需执行以下代码:

      foreach (CategoryProductsResult categoryProductsResult in categoryProductsResults.Where(categoryProductsResult => resultSet.ProductId !=categoryProductsResult.ProductId)
      {
          resultSet.Add(categoryProductsResult);
      }
      

      【讨论】:

        【解决方案4】:

        列表中的引用对象由它们的哈希码索引。因此,Contains 永远不会找到具有相同哈希码的引用对象(除非您覆盖类中的 GetHashCodeEquals 实现。

        SO answer 解释。

        【讨论】:

          【解决方案5】:

          您需要检查当前项目是否包含在每次迭代的目标列表中。目前,您在循环开始时检查一次,这意味着您的所有项目都不在目标列表中。

          我认为Distinct 已经在做你想做的事了,你可能想使用这个扩展而不是你自己的循环。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2016-12-01
            • 1970-01-01
            • 2016-09-01
            • 2012-07-11
            • 2018-04-08
            • 2017-04-20
            • 2018-10-02
            • 2016-09-04
            相关资源
            最近更新 更多