为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()吗?

为ValueObjects实现GetHashCode和Equals方法

正确地表示GetHashCode期望相等的实体返回相同的哈希码。因为两个实体的相等性是通过代码的比较得到的。

另一方面,这意味着对于不相等的实体,哈希码的唯一性必须得到保证,尽可能多。

Equals和GetHashCode的文档很好地解释了这一点,并包括关于值对象实现的具体指导。对于值对象,如果对象类型相同且公共字段和私有字段相等,则Equals为true。然而,这个解释适用于框架值类型,你可以自由地通过覆盖它来创建自己的Equals。

GetHashCode有两个必须遵循的规则:

  • 如果两个对象比较相等,则每个对象的GetHashCode方法必须返回相同的值。但是,如果两个对象没有如果两个对象的GetHashCode方法相等,则不相等

  • 对象的GetHashCode方法必须一致地返回相同的哈希码,只要没有修改对象的状态它决定了对象的Equals方法的返回值。请注意这只适用于应用程序的当前执行,如果应用程序是,则可以返回不同的哈希码再次运行。