我有以下类(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/