我经常发现我的自我重写Equals()
和GetHashCode()
来实现具有相同属性值的业务对象相等的语义。这会导致代码重复写入并且易于维护(属性被添加,并且一个/两个覆盖都不会更新)。
代码最终看起来像这样(欢迎对实现的评论):
public override bool Equals(object obj)
{
if (object.ReferenceEquals(this, obj)) return true;
MyDerived other = obj as MyDerived;
if (other == null) return false;
bool baseEquals = base.Equals((MyBase)other);
return (baseEquals &&
this.MyIntProp == other.MyIntProp &&
this.MyStringProp == other.MyStringProp &&
this.MyCollectionProp.IsEquivalentTo(other.MyCollectionProp) && // See http://stackoverflow.com/a/9658866/141172
this.MyContainedClass.Equals(other.MyContainedClass));
}
public override int GetHashCode()
{
int hashOfMyCollectionProp = 0;
// http://computinglife.wordpress.com/2008/11/20/why-do-hash-functions-use-prime-numbers/
// BUT... is it worth the extra math given that elem.GetHashCode() should be well-distributed?
int bitSpreader = 31;
foreach (var elem in MyCollectionProp)
{
hashOfMyCollectionProp = spreader * elem.GetHashCode();
bitSpreader *= 31;
}
return base.GetHashCode() ^ // ^ is a good combiner IF the combined values are well distributed
MyIntProp.GetHashCode() ^
(MyStringProp == null ? 0 : MyStringProp.GetHashValue()) ^
(MyContainedClass == null ? 0 : MyContainedClass.GetHashValue()) ^
hashOfMyCollectionProp;
}
我的问题
答案 0 :(得分:4)
MSDN实际上不说“不要为可变类型重载Equals等”。它曾经说过,但现在却说:
定义类或结构时,您可以决定它是否有意义 为...创建值相等(或等价)的自定义定义 类型。通常,您在对象时实现值相等 类型应该被添加到某种类型的集合中,或者何时添加 它们的主要目的是存储一组字段或属性。
http://msdn.microsoft.com/en-us/library/dd183755.aspx
但是,当一个对象参与散列集合(Dictionary<T,U>
,HashSet<T>
等)时,哈希码的稳定性仍然存在复杂性。
我决定选择两全其美,如下所述:
答案 1 :(得分:1)
我经常发现我的自我重写Equals()和GetHashCode()
鉴于贡献组件值分布均匀,是否足够?
int
属性。建议使用一些(小)素数进行移位。 答案 2 :(得分:0)
也许我在这里很困惑,但是null
检查不应该在GetHashCode
覆盖中返回1而不是0?
所以
MyStringProp == null ? 0 : MyStringProp.GetHashValue()
应该是
MyStringProp == null ? 1 : MyStringProp.GetHashValue()