C# 列表重复

本文关键字:列表 | 更新日期: 2023-09-27 18:29:20

我想知道为什么当我尝试在重复时不将我的对象添加到列表中时,它仍然在添加它

if (thePreviousList.Contains(thePreviousItem))
{
}
else
{
    thePreviousList.Add(thePreviousItem);
}

例如,上一个项 id = 1 和名称 = 测试如果我有另一个具有相同 id 和相同名称的对象,它仍然会添加它......

C# 列表重复

您需要

在尝试添加到列表中的对象上正确实现Equals方法。若要确定列表是否已包含传递的对象,Contains方法使用 Equals

如果不想重写 Equals,可以使用 LINQ 检查是否已存在具有相同 ID 和名称的对象(不一定是相同的对象(:

if (thePreviousList.Any(item => item.ID == thePreviousItem.ID
                             && item.Name == thePreviousItem.Name)) 
{ 
} 
else 
{ 
    thePreviousList.Add(thePreviousItem); 
} 

从文档中:

此方法通过使用默认相等比较器

来确定相等性,该比较器由对象的 IEquatable(Of T( 实现所定义。T 的等于方法(列表中的值的类型(。

如果您尚未实现 IEquatable<T>.Equals ,则使用默认值,即引用相等性。或者,您实现了IEquatable<T>.Equals,但没有正确执行。

例如,上一个项目 id = 1 和名称 = test 如果我有另一个具有相同 id 和相同名称的对象,它仍然会添加它......

你需要类似的东西

class Foo : IEquatable<Foo> {
    public int Id { get; private set; }
    public string Name { get; private set; }
    public Foo(int id, string name) {
        this.Id = id;
        this.Name = name;
    }
    public bool Equals(Foo other) {
        return this.Id == other.Id && this.Name == other.Name;
    }
}

最后,如果检查重复项是您要做很多的事情,那么您不应该使用 List<T> .您应该使用 HashSet<T> .

从您对其他答案的评论中听起来您不想覆盖Equals.

您可以改为执行以下操作:

if (thePreviousList.Any(item => thePreviousItem.id == item.id && thePreviousItem.name == item.name))
{
}
else
{
    thePreviousList.Add(thePreviousItem);
}

因为List<>.Contains正在检查引用而不检查列表中对象的属性。

为此,您应该覆盖Equals,并且为了最佳实践,也覆盖GetHashCode。规则应该是当Equals返回 true 时,应返回相同的哈希代码。

像下面这样的东西就足够了:

public override bool Equals(object obj)
{
   var i = obj as YourType;
   if(i == null) return false;
   return i.Id == this.Id && i.Name == this.Name;
}
public override int GetHashCode()
{
   return this.Id.GetHashCode() ^ this.Name.GetHashCode();
}