仅当基本 Equals 被重写时才调用 IEquatables 实现
我有以下类
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,这是为什么?
I have the following class
class Product : IEquatable<Product>
{
public Guid Id { get; set; }
public bool Equals(Product other)
{
return Id.Equals(other.Id);
}
}
If i try and create a unique list of the items of a list as follows
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);
two items are returned, this occurs until I override the object.Equals method, once i do this and my code is as follows
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();
}
}
my IEquatable Equals method is now called, but only if i override the base method, furthermore if i put a breakpoint on the object equals method it is never called.
Why is this?
----UPDATE
So with the product class
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();
}
}
If GetHashCode is removed, The IEquatable implementation of Equals is never hit I understand you should generally implement Equals and GetHashCode together, is this why?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
问题在于原始实现中您没有重写
GetHashcode
方法。在底层,Union
使用Set
样式结构来删除重复项。该结构根据GetHashCode
返回的值将对象放入存储桶中。如果相等对象之间的哈希码不匹配(这是必须的),那么它们可能会被放入不同的存储桶中,并且永远不会与Equals
进行比较。一般来说,如果您实现
IEquatable;
你应该总是Object.Equals
Object.GetHashCode
如果两者不做,你就会陷入这样的情况。
请注意,您的实现可以稍微简化一些
The problem is in the original implementation you're not overriding the
GetHashcode
method. Under the hoodUnion
uses aSet<T>
style structure to remove duplicates. This structure puts objects into buckets based on the value returned fromGetHashCode
. If the hash code doesnt't match up between equal objects (which it must do) then they can potentially be put in different buckets and never compared withEquals
In general if you implement
IEquatable<T>
you should alwaysObject.Equals
Object.GetHashCode
Not doing both will land you in situations like this.
Note, your implementation could be simplified a bit
Enumerable.Union 的文档说:
您正在实施
IEquatable
。您需要实现IEqualityComparer
。Documentation for Enumerable.Union says:
You're implementing
IEquatable
. You need to implementIEqualityComparer
.