【问题标题】:C# List duplicateC# 列表重复
【发布时间】:2012-04-13 06:36:58
【问题描述】:

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

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

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

【问题讨论】:

  • 也许你想使用Dictionary(Of TKey, TValue)而不是列表

标签: c# asp.net list duplicates


【解决方案1】:

您需要在您尝试添加到列表中的对象上正确实现Equals 方法。判断列表是否已经包含传入的对象,Contains方法使用Equals

【讨论】:

  • 如果有重复,我该怎么做才能不在列表中添加对象?不使用equals方法?
  • 为什么不想使用Equals 方法?这是最简单的事情。
  • @Emged 您可以使用不接受重复的集合(即集合,例如 HashSet)并提供比较器,或者您可以编写自己的 Contains 方法来搜索列表使用自定义比较器查找项目。
【解决方案2】:

因为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();
}

【讨论】:

  • 如果有重复,我该怎么做才能不在列表中添加对象?
  • @Emged - 查看更新(虽然我在下面看到你关于不使用 Equals 的评论 - 这总是让我感到困惑......你为什么想做除了 right i> 方式?)
【解决方案3】:

来自文档:

此方法通过使用默认相等比较器来确定相等性,该比较器由对象的 IEquatable(Of T).Equals 方法(列表中值的类型)的实现定义。

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

例如,前一个项目 id = 1 和 name = 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&lt;T&gt;。你应该使用HashSet&lt;T&gt;

【讨论】:

  • 你不一定需要实现IEquatable&lt;T&gt;,覆盖Equals就足够了,因为如果IEquatable&lt;&gt;没有实现,默认的比较器会调用Equals
【解决方案4】:

您的 cmets 听到您不想覆盖 Equals 的其他答案。

您可以改为这样做:

if (thePreviousList.Any(item => thePreviousItem.id == item.id && thePreviousItem.name == item.name))
{

}
else
{
    thePreviousList.Add(thePreviousItem);
}

【讨论】:

    【解决方案5】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-11-30
      • 1970-01-01
      • 1970-01-01
      • 2018-06-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-06
      相关资源
      最近更新 更多