我有一个包含对象的列表,但这些对象在列表中不是唯一的。我想这个代码在另一个列表中使它们独一无二:
foreach (CategoryProductsResult categoryProductsResult in categoryProductsResults.Where(categoryProductsResult => !resultSet.Contains(categoryProductsResult)))
{
resultSet.Add(categoryProductsResult);
}
但最后resultSet与categoryProductsResults相同。
categoryProductsResult的第二行:
resultSet第一行:
正如您可以看到resultSet的第一行和categoryProductsResult的第二行相同,但它将第二行添加到resultSet。
你有什么建议吗?
答案 0 :(得分:13)
Contains
使用默认比较器来比较引用,因为您的类没有覆盖Equals
和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();
答案 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
永远不会找到具有相同哈希码的引用对象(除非您覆盖类中的GetHashCode
和Equals
实现。
这SO answer解释了。
答案 4 :(得分:0)
您需要检查当前项目是否包含在每次迭代的目标列表中。目前,您在循环开始时检查一次,这意味着您的所有项目都不在目标列表中。
我认为Distinct已经做了你想做的事情,你可能想要使用这个扩展而不是你自己的循环。