【发布时间】:2012-03-14 18:29:10
【问题描述】:
我发现自己经常重写 Equals() 和 GetHashCode() 以实现具有相同属性值的业务对象相等的语义。这会导致代码重复编写且维护脆弱(添加了属性并且其中一个/两个覆盖没有更新)。
代码最终看起来像这样(欢迎使用 cmets 实现):
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;
}
我的问题
- 实施模式是否合理?
- 考虑到贡献的组件值分布良好,^ 是否足够?考虑到它们的散列分布良好,在组合集合元素时是否需要乘以 31 比 N?
- 似乎可以将此代码抽象为使用反射来确定公共属性的代码,构建与手动编码解决方案匹配的表达式树,并根据需要执行表达式树。这种方法看起来合理吗?某处是否有现成的实现?
【问题讨论】:
-
为什么投反对票(发布后一年多)?这个问题非常合理。如果有什么问题,请说出来。
标签: c# equals hashcode maintainability