什么是覆盖案例的GetHashCode
函数的最佳方法,何时
如果其中至少有一个字段匹配,则我的对象被视为相等。
对于通用Equals
方法,示例可能如下所示:
public bool Equals(Whatever other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
// Considering that the values can't be 'null' here.
return other.Id.Equals(Id) || Equals(other.Money, Money) ||
Equals(other.Code, Code);
}
尽管如此,我对于为这种情况做出良好的GetHashCode
实施感到困惑。
应如何做?
谢谢。
答案 0 :(得分:17)
这是Equals
的可怕定义,因为它不具有传递性。
考虑
x = { Id = 1, Money = 0.1, Code = "X" }
y = { Id = 1, Money = 0.2, Code = "Y" }
z = { Id = 3, Money = 0.2, Code = "Z" }
然后x == y
和y == z
,但x != z
。
此外,我们可以确定GetHashCode
的唯一合理实现是一个常量映射。
假设x
和y
是不同的对象。让z
成为对象
z = { Id = x.Id, Money = y.Money, Code = "Z" }
然后x == z
和y == z
,以便x.GetHashCode() == z.GetHashCode()
和y.GetHashCode() == z.GetHashCode()
建立x.GetHashCode() == y.GetHashCode()
。由于x
和y
是任意的,我们已确定GetHashCode
是常数。
因此,我们已经证明GetHashCode
唯一可能的实现是
private readonly int constant = 17;
public override int GetHashCode() {
return constant;
}
所有这些结合在一起表明你需要重新思考你正在尝试模型的概念,并提出Equals
的不同定义。
答案 1 :(得分:7)
我认为你不应该使用Equals。人们有一个非常明确的概念,即等于什么意思,如果ID不同但代码或名称相同,我不会认为那些“平等”。也许你需要一种不同的方法,比如“IsCompatible”。
如果您希望能够对它们进行分组,可以在这些对象的列表上使用扩展方法ToLookup(),以使用谓词,这将是您的IsCompatible方法。然后他们将被分组。
答案 2 :(得分:6)
黄金法则是:如果对象比较相等,则必须生成相同的哈希码。
因此,符合(但假设,不合需要)的实施将是
public override int GetHashCode()
{
return 0;
}
坦率地说,如果Id
,Name
和Code
彼此独立,那么我不知道你是否可以做得更好。将这种类型的对象放在哈希表中会很痛苦。