只在基类Equals被重写时调用equatables实现

本文关键字:调用 equatables 实现 重写 基类 Equals | 更新日期: 2023-09-27 18:10:12

我有以下类

    class Product : IEquatable<Product>
{
    public Guid Id { get; set; }
    public bool Equals(Product other)
    {
        return Id.Equals(other.Id);
    }
}

如果我尝试创建一个包含列表项的唯一列表,如下所示

            Guid a = Guid.NewGuid();
        List<Product> listA = new List<Product>();
        listA.Add(new Product(){Id = a});
        List<Product> listB = new List<Product>();
        listB.Add(new Product()
        {
            Id = a
        });
        Debug.Assert(listA.Union(listB).Count()==1);

返回两项,直到我覆盖该对象为止。Equals方法,一旦我这样做了,我的代码如下

class Product : IEquatable<Product>
{
    public Guid Id { get; set; }
    public bool Equals(Product other)
    {
        if (ReferenceEquals(null, other)) return false;
        if (ReferenceEquals(this, other)) return true;
        return other.Id.Equals(Id);
    }
    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        if (obj.GetType() != typeof (Product)) return false;
        return Equals((Product) obj);
    }
    public override int GetHashCode()
    {
        return Id.GetHashCode();
    }
}

我的IEquatable Equals方法现在被调用,但只有当我覆盖基方法时,而且如果我在object Equals方法上设置了一个断点,它永远不会被调用。

为什么会这样?

——更新

对于product类

    class Product : IEquatable<Product>
{
    public Guid Id
    {
        get;
        set;
    }
    public bool Equals(Product other)
    {
        return Id.Equals(other.Id);
    }
    public override int GetHashCode()
    {
        return Id.GetHashCode();
    }
}

如果GetHashCode被删除,等号的等价实现永远不会命中我理解你通常应该实现等号和GetHashCode在一起,这是为什么?

只在基类Equals被重写时调用equatables实现

问题是在原始实现中,您没有重写GetHashcode方法。在引擎盖下,Union使用Set<T>风格的结构来删除重复项。该结构根据GetHashCode返回的值将对象放入桶中。如果哈希码在相等的对象之间不匹配(这是必须的),那么它们可能被放在不同的桶中,并且永远不会与Equals

进行比较。

一般来说,如果你实现IEquatable<T>,你应该总是

  • 覆盖Object.Equals
  • 覆盖Object.GetHashCode
不做这两件事会让你陷入这样的境地。

注意,您的实现可以简化一点

class Product : IEquatable<Product>
{
  public Guid Id { get; set; }
  public bool Equals(Product other) 
  {
    if (ReferenceEquals(null, other)) {
      return false;
    }
    return other.Id == this.Id;
  }
  public override bool Equals(object obj) 
  {
    return Equals(obj as Product);
  }    
  public override int GetHashCode()
  {
    return Id.GetHashCode();
  }
}

Enumerable文档。联盟说:

默认的相等比较器default用于比较实现了IEqualityComparer(Of T)泛型的类型接口。要比较自定义数据类型,需要实现这个,并提供自己的GetHashCode和Equals方法类型。

你正在执行IEquatable。您需要实现IEqualityComparer