List.Contains无法正常工作

时间:2013-02-22 09:19:49

标签: c# linq list

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

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

但最后resultSet与categoryProductsResults相同。

categoryProductsResult的第二行:

enter image description here

resultSet第一行:

enter image description here

正如您可以看到resultSet的第一行和categoryProductsResult的第二行相同,但它将第二行添加到resultSet。

你有什么建议吗?

5 个答案:

答案 0 :(得分:13)

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();

答案 1 :(得分:3)

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);

答案 2 :(得分:1)

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

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

答案 3 :(得分:0)

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

SO answer解释了。

答案 4 :(得分:0)

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

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