5

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

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

但最终 resultSet 与 categoryProductsResults 相同。

categoryProductsResult 的第二行:

在此处输入图像描述

结果集第一行:

在此处输入图像描述

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

你有什么建议吗?

4

5 回答 5

13

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

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();
于 2013-02-22T09:24:34.240 回答
3

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

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

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

布尔包含 = list.Any(i => i.Id == obj.Id);

于 2013-02-22T09:23:15.153 回答
1

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

foreach (CategoryProductsResult categoryProductsResult in categoryProductsResults.Where(categoryProductsResult => resultSet.ProductId !=categoryProductsResult.ProductId)
{
    resultSet.Add(categoryProductsResult);
}
于 2013-02-22T09:27:14.673 回答
0

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

这个SO 答案解释了。

于 2013-02-22T09:22:53.153 回答
0

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

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

于 2013-02-22T09:24:53.993 回答