-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 9 posts ] 
Author Message
 Post subject: how to implement GetHashCode()
PostPosted: Sun Jan 14, 2007 1:46 pm 
Regular
Regular

Joined: Fri Feb 03, 2006 5:28 pm
Posts: 73
Location: Québec, QC, Canada
Hi,

let's say I have a class like this:

public class Announcement
{
private long _idAnnouncement;
public long IdAnnouncement
{
get;
}

private string _title;
public string Title
{
get;
set;
}

private string _announcement;
public string Announcement
{
get;
set;
}

private DateTime _creationDate;
public DateTime CreationDate
{
get;
set;
}
}


what would be the best way to overload GetHashCode?

And is it safe to compare both HashCode in que Equals method in order to evaluate equality?

Thanks


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 15, 2007 3:12 am 
Regular
Regular

Joined: Tue Feb 21, 2006 9:50 am
Posts: 107
For this (and other reasons) i define an object id for all my persistent classes. I have a base class like this:

Code:
internal class BasePersistentObject
{
  private Guid mObjectId = Guid.NewGuid();

  internal Oid
  {
    get { return mObjectId; }
  }

  public override bool Equals(object pToCompare)
  {
    if ( this == pToCompare )
    {
      return true;
    }
    if ( (null == pToCompare) || (pToCompare.GetType() != GetType()) )
    {
      return false;
     }
     BasePersitentObject toCompare = (BasePersistentObject)pToCompare;
    return (toCompare != null) && (Oid == toCompare.Oid);
  }

  public override int GetHashCode()
  {
    int hash = 57;
    hash = 27 * hash * Oid.GetHashCode();
    return hash;
  }
}


This code works fine for me.

Regards
Klaus


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 15, 2007 4:11 am 
Regular
Regular

Joined: Tue Aug 08, 2006 4:28 am
Posts: 96
Location: Hong Kong
Klaus,

Do you persist the property Oid to database? If not, what's the reason to override GetHashCode() and Equal()? Thanks.

Regards,

Ken


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 15, 2007 8:04 am 
Regular
Regular

Joined: Tue Feb 21, 2006 9:50 am
Posts: 107
No, it's just for internal purpose and isn't stored in the database. We have added the Oid just to have an easy way to identify a specific instance of an object.

From our point of view two instances of a persistent class are identical, if they share the same primary key. For newly created instances of persistent objects you can't set the primary key if you want NHibernate to detect automatically if it has to insert or update. In this state the only way to find out if two instances are identical is to compare all fields of the instances to each other. To avoid this we introduced the Oid.

Regards
Klaus


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 15, 2007 9:08 am 
Regular
Regular

Joined: Fri Feb 03, 2006 5:28 pm
Posts: 73
Location: Québec, QC, Canada
Thanks.

In the GetHashCode, what's the 57 and 27 ?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 15, 2007 9:36 pm 
Regular
Regular

Joined: Tue Aug 08, 2006 4:28 am
Posts: 96
Location: Hong Kong
Klaus,


You are right. But there is one thing I do not understand. Do "this == pToCompare" and "this.Oid == pToCompare.Oid" always return the same value?

Regards,

Ken


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 16, 2007 2:47 am 
Regular
Regular

Joined: Tue Feb 21, 2006 9:50 am
Posts: 107
to martlb:
this values are taken from a sample implementation of GetHashcode (could not remember from where i took this but i think it was a sample from MS$ ;-). If i remember right this multiplicator should help to generate unique hash codes. In principle it should be fine to use just Oid.GetHashCode() because a guid is unique per definition.

to canton:

no, "this == pToCompare" checks if both references point to the same instance, "this.Oid == pToCompare.Oid" checks if both instances contains the same persistent object.

For our project this approach fits. Another approach will be to check the equality by all fields or by the business key of a persistent objects. The book "Hibernate in action" is a good source for this even if it focus on Java.

Regards
Klaus


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 16, 2007 4:11 am 
Regular
Regular

Joined: Tue Aug 08, 2006 4:28 am
Posts: 96
Location: Hong Kong
Klaus,


Thanks for reply.

I know the syntax :)

Could you show a scenario that following evaluates to true?
Code:
this != pToCompare && this.Oid == pToCompare.Oid


I ask this because I think "this == pToCompare" and "this.Oid == pToCompare.Oid" will always return the same value (semantically! not syntactically) and I know the following could not happen
Code:
this == pToCompare && this.Oid != pToCompare.Oid



Regards,

Ken


Top
 Profile  
 
 Post subject: Hello
PostPosted: Tue Jan 16, 2007 5:15 am 
Newbie

Joined: Tue Jan 16, 2007 4:44 am
Posts: 5
For an "easy to understand and efficient" code, i would suggest these simple rules (i may be wrong :) :

1) Never put a persistent object in an ISet before its keys are defined

2) Always use the primary key attributes' GetHashCode and Equals (I know this is supposed to be 'bad' because these values may change but, if you follow the rule #1, it won't break anything)


So let's say you have an Article and its pk is 'Id' (long)

I would create :

Code:
public override bool Equals(object other) {
  if (other is Article) {
    return Id.Equals(((Article) other).Id);
  } else {
    return false;
  }
}


and

Code:
public override int GetHashCode() {
    return Id.ToString().GetHashCode();
}


And if you have a composite pk, let's say an orderLine (bad idea for an order line but just for the example), whose key atributes are : orderId and articleId.

Code:
public override bool Equals(object other) {
  if (other is OrderLine) {
    return
      OrderId.Equals(((OrderLine) other).OrderId)
      && ArticleId.Equals(((OrderLine) other).ArticleId);
  } else {
    return false;
  }
}


and

Code:
public override int GetHashCode() {
    return (OrderId.ToString() +"|" + ArticleId.ToString()) .GetHashCode();
}




Finally, I would say that an Equals() method that doesn't reflect the business Equality is definitly wrong and will lead you into errors.

If you want to check the address equality, just compare the instances with the "==" operator.

_________________
=====
Nhibernate rox !

here is my (empty) blog


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 9 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.