为Value Objects实现GetHashCode和Equals方法

时间:2013-04-11 10:59:29

标签: c# nhibernate

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

2 个答案:

答案 0 :(得分:1)

正确地表示GetHashCode期望的实体返回相同的哈希码。因为通过比较该代码来实现2个实体的相等性。

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

答案 1 :(得分:1)

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

GetHashCode必须遵循两条规则:

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

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

  •