[英]Simplify Overriding Equals(), GetHashCode() in C# for Better Maintainability
I find my self overriding Equals()
and GetHashCode()
frequently to implement the semantic that business objects with identical property values are equal. 我经常发现我的自我重写
Equals()
和GetHashCode()
来实现具有相同属性值的业务对象相等的语义。 That leads to code that is repetitive to write and fragile to maintain (property gets added and one/both of the overrides are not updated). 这会导致代码重复写入并且易于维护(属性被添加,并且一个/两个覆盖都不会更新)。
The code ends up looking something like this (comments on the implementation are welcome): 代码最终看起来像这样(欢迎对实现的评论):
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;
}
My Questions 我的问题
MSDN actually doesn't say "don't overload Equals et al for mutable types". MSDN实际上并没有说“不要为可变类型重载Equals等”。 It used to say that, but now it says:
它曾经说过,但现在它说:
When you define a class or struct, you decide whether it makes sense to create a custom definition of value equality (or equivalence) for the type.
定义类或结构时,您可以决定是否为类型创建值相等(或等效)的自定义定义。 Typically, you implement value equality when objects of the type are expected to be added to a collection of some sort, or when their primary purpose is to store a set of fields or properties.
通常,当期望将类型的对象添加到某种类型的集合时,或者当它们的主要目的是存储一组字段或属性时,实现值相等。
http://msdn.microsoft.com/en-us/library/dd183755.aspx http://msdn.microsoft.com/en-us/library/dd183755.aspx
Still, there are complexities surrounding stability of the hash code while an object participates in a hashed collection ( Dictionary<T,U>
, HashSet<T>
, etc.). 然而,当对象参与散列集合(
Dictionary<T,U>
, HashSet<T>
等)时,存在围绕哈希码的稳定性的复杂性。
I decided to opt for the best of both worlds, as outlined here: 我决定选择两全其美,如下所述:
https://stackoverflow.com/a/9752155/141172 https://stackoverflow.com/a/9752155/141172
I find my self overriding Equals() and GetHashCode() frequently
我发现我的自我经常覆盖Equals()和GetHashCode()
Is ^ adequate given that the contributing component values are well-distributed?
鉴于贡献组件值分布均匀,是否足够?
int
properties. int
属性。 Shifting with some (small) prime numbers is advised. Perhaps I'm confused here, but shouldn't the on null
check return a 1 instead of a 0 in the GetHashCode
override? 也许我在这里很困惑,但是在
GetHashCode
覆盖中,on null
check不应该返回1而不是0?
So 所以
MyStringProp == null ? 0 : MyStringProp.GetHashValue()
should be 应该
MyStringProp == null ? 1 : MyStringProp.GetHashValue()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.