为ValueObjects实现GetHashCode和Equals方法
本文关键字:Equals 方法 GetHashCode ValueObjects 实现 | 更新日期: 2023-09-27 18:08:42
NHibernate
文档中的一段:
注意:如果你定义了一个复合元素的
ISet
,正确实现Equals()
和GetHashCode()
是非常重要的。
这里的correctly
是什么意思?是否有必要实现这些方法的所有值对象的领域?
在文章Marc附加用户Albic声明:
正确实现
GetHashCode()
实际上非常困难,因为除了Marc已经提到的规则外,哈希码在对象的生命周期内不应该更改。因此,用于计算哈希码的字段必须是不可变的。当我与
NHibernate
一起工作时,我终于找到了解决这个问题的方法。我的方法是从对象的ID计算哈希码。ID只能通过构造函数设置,所以如果你想改变ID,这是不太可能的,你必须创建一个新的对象,它有一个新的ID,因此一个新的哈希码。这种方法最适合guid,因为你可以提供一个随机生成ID的无参数构造函数。
我突然意识到我的AbstractEntity
类里面有什么:
public abstract class AbstractEntity<T> where T : AbstractEntity<T> {
private Nullable<Int32> hashCode;
public virtual Guid Id { get; protected set; }
public virtual Byte[] Version { get; set; }
public override Boolean Equals(Object obj) {
var other = obj as T;
if(other == null) {
return false;
}
var thisIsNew = Equals(this.Id, Guid.Empty);
var otherIsNew = Equals(other.Id, Guid.Empty);
if(thisIsNew && otherIsNew) {
return ReferenceEquals(this, other);
}
return this.Id.Equals(other.Id);
} // public override Boolean Equals(Object obj) {
public override Int32 GetHashCode() {
if(this.hashCode.HasValue) {
return this.hashCode.Value;
}
var thisIsNew = Equals(this.Id, Guid.Empty);
if(thisIsNew) {
this.hashCode = base.GetHashCode();
return this.hashCode.Value;
}
return this.Id.GetHashCode();
} // public override Int32 GetHashCode() {
public static Boolean operator ==(AbstractEntity<T> l, AbstractEntity<T> r) {
return Equals(l, r);
}
public static Boolean operator !=(AbstractEntity<T> l, AbstractEntity<T> r) {
return !Equals(l, r);
}
} // public abstract class AbstractEntity<T>...
由于所有components
都嵌套在entities
中,我应该为它们实现Equals()
和GetHashCode()
吗?
正确地表示GetHashCode
为期望相等的实体返回相同的哈希码。因为两个实体的相等性是通过代码的比较得到的。
另一方面,这意味着对于不相等的实体,哈希码的唯一性必须得到保证,尽可能多。
Equals和GetHashCode的文档很好地解释了这一点,并包括关于值对象实现的具体指导。对于值对象,如果对象类型相同且公共字段和私有字段相等,则Equals为true。然而,这个解释适用于框架值类型,你可以自由地通过覆盖它来创建自己的Equals。
GetHashCode有两个必须遵循的规则:
如果两个对象比较相等,则每个对象的GetHashCode方法必须返回相同的值。但是,如果两个对象没有如果两个对象的GetHashCode方法相等,则不相等
对象的GetHashCode方法必须一致地返回相同的哈希码,只要没有修改对象的状态它决定了对象的Equals方法的返回值。请注意这只适用于应用程序的当前执行,如果应用程序是,则可以返回不同的哈希码再次运行。