c# - IEquatables 实现仅在基础 Equals 被覆盖时调用

标签 c# .net generics

我有以下类(class)

    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);

两个项目被返回,这发生直到我重写 object.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 方法现在被调用,但前提是我覆盖了基本方法,此外,如果我在对象 equals 方法上放置了一个断点,它永远不会被调用。

这是为什么?

----更新

产品类也是如此

    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,Equals 的 IEquatable 实现永远不会命中我知道您通常应该一起实现 Equals 和 GetHashCode,这是为什么?

最佳答案

问题出在原始实现中,您没有覆盖 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();
  }
}

关于c# - IEquatables 实现仅在基础 Equals 被覆盖时调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7612910/

相关文章:

generics - 返回映射的通用函数

c# - Selenium:如何通过部分 href 查找元素?

.net - .Net 中的套接字服务器、SocketAsyncEventArgs 和并发连接

c# - Docker 在 VS 中运行,但在发布到 AWS 时出错?错误 CS5001 : Program does not contain a static 'Main' method suitable for an entry point

.net - 基于现有模板生成Word文档的最佳方法是什么

c# - 打印可滚动的窗口窗体。

c# - 将字典转换为 List<KeyValuePair>

java - Kryo 通用读写

c# - 在 Polly 中结合 transient 故障捕获和重新授权

c# - 使用 JSON.NET 反序列化任何内容