Equals和GetHashCode的最佳策略是什么?

tuc*_*caz 36 .net c# equals gethashcode

我正在使用域模型,并且正在思考我们在.NET中实现这两种方法的各种方法.你最喜欢的策略是什么?

这是我目前的实施:

public override bool Equals(object obj)
{
    var newObj = obj as MyClass;

    if (null != newObj)
    {
        return this.GetHashCode() == newObj.GetHashCode();
    }
    else
    {
        return base.Equals(obj);
    }
}

// Since this is an entity I can use its Id
// When I don't have an Id, I usually make a composite key of the properties
public override int GetHashCode()
{
    return String.Format("MyClass{0}", this.Id.ToString()).GetHashCode();
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*ann 35

领域驱动设计区分了实体价值对象.这是一个很好的区分,因为它指导你如何实现Equals.

如果它们的ID彼此相等,则实体是相等的.

如果所有(重要)组成元素彼此相等,则值对象相等.

在任何情况下,GetHashCode的实现应基于用于确定相等性的相同值.换句话说,对于实体,哈希码应该直接从ID计算,而对于值对象,应该从所有组成值计算.


eri*_*len 6

假设实例相等是因为哈希码相等是错误的。

我猜你的 GetHashCode 实现没问题,但我通常使用类似的东西:

public override int GetHashCode() {
    return object1.GetHashCode ^ intValue1 ^ (intValue2 << 16);
}
Run Code Online (Sandbox Code Playgroud)

  • 我真的不明白你对@tucaz 提出的问题的回答有什么意义。 (4认同)
  • 我知道这是个老问题,但你能解释一下你在这里使用的表达吗 (2认同)

Eri*_*ikE 5

这里的答案都没有真正适合我.既然你已经说过你不能Id用于平等,而你需要使用一组属性,这是一个更好的方法.注意:我不认为这总体上是实现Equals和实现的最佳方式GetHashCode.这是OP代码的更好版本.

public override bool Equals(object obj) {
   var myClass = obj as MyClass;

   if (myClass != null) {
      // Order these by the most different first.
      // That is, whatever value is most selective, and the fewest
      // instances have the same value, put that first.
      return this.Id == myClass.Id
         && this.Name == myClass.Name
         && this.Quantity == myClass.Quantity
         && this.Color == myClass.Color;
   } else {
      // This may not make sense unless GetHashCode refers to `base` as well!
      return base.Equals(obj);
   }
}

public override int GetHashCode() {
   int hash = 19;
   unchecked { // allow "wrap around" in the int
      hash = hash * 31 + this.Id; // assuming integer
      hash = hash * 31 + this.Name.GetHashCode();
      hash = hash * 31 + this.Quantity; // again assuming integer
      hash = hash * 31 + this.Color.GetHashCode();
   }
   return hash;
}
Run Code Online (Sandbox Code Playgroud)

请参阅Jon Skeet的回答,了解其背后的一些原因.使用xor并不好,因为各种数据集最终会导致相同的散列.这种具有素数的环绕方法(上面的种子值为19和31,或者您选择的其他值)可以更好地分割成每个碰撞很少的"桶".

如果您的任何值可以为null,我建议您仔细考虑它们应如何比较.您可以使用短路空值评估和空合并运算符.但是请确保如果null值应该相等,那么当它们为null时,将不同的哈希代码分配给不同的可空属性.

另外,我不相信你的Equals实现有任何意义.当比较两个对象的相等性时,首先GetHashCode比较它们的值.只有当这些方法不同时才Equals运行方法(因此,如果散列到相同值的两个对象不同,则会检测到这个).由于您的GetHashCode实现没有引用base,因此您的Equals方法可能没有意义.具体来说,如果Equals对于哈希码不同的两个对象可以返回true ,则会有一个严重的错误等待破解.


归档时间:

查看次数:

13394 次

最近记录:

6 年,11 月 前