来自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()
吗?
答案 0 :(得分:1)
正确地表示GetHashCode
为期望的实体返回相同的哈希码。因为通过比较该代码来实现2个实体的相等性。
另一方面,这意味着对于不相等的实体,哈希代码的唯一性必须尽可能保证。
答案 1 :(得分:1)
Equals和GetHashCode的文档很好地解释了这一点,并包含了有关值对象实现的具体指导。对于值对象,如果对象是相同类型且公共字段和私有字段相等,则Equals为true。但是,此解释适用于框架值类型,您可以通过覆盖它来创建自己的Equals。
GetHashCode必须遵循两条规则:
如果两个对象比较相等,则每个对象的GetHashCode方法必须返回相同的值。但是,如果两个对象没有 比较相同,两个对象的GetHashCode方法不相同 必须返回不同的值。
对象的GetHashCode方法必须始终返回相同的哈希码,只要对象状态没有修改即可 它确定对象的Equals方法的返回值。注意 这只适用于当前执行的应用程序, 并且如果应用程序是,则可以返回不同的哈希码 再跑一次。