GetHashCode issue

G

Guest

I've an issue when overriding GetHashCode methods. For instance, an
hypothetical Circle object may have its hashcode defined as x ^ y ^ diameter.
This works fine as long as the object is not modified (otherwise it doesn't
work).

Microsoft states the following: "The hash function must return exactly the
same value regardless of any changes that are made to the object". It means
that you should base your hashcode on properties that will not change. How to
proceed when all the properties can change (as in the above Circle)? Define a
"fake" constant property? How to define it? Or has someone a elegant strategy?

Thanks in advance!!
 
S

Senthil Kumar

I can't see any other way other than making Circle immutable (like
String). If the user wants to modify, he/she must create a new instance
(Clone()?).

Regards
Senthil Kumar
 
G

Guest

Thanks! But actually the object in question is not as simple as Circle ;-) so
I would like to avoid to duplicate it if possible... but maybe it is not
possible!
 
M

Michael S

Patrick Hertzog said:
I've an issue when overriding GetHashCode methods. For instance, an
hypothetical Circle object may have its hashcode defined as x ^ y ^
diameter.
This works fine as long as the object is not modified (otherwise it
doesn't
work).

Microsoft states the following: "The hash function must return exactly the
same value regardless of any changes that are made to the object". It
means
that you should base your hashcode on properties that will not change. How
to
proceed when all the properties can change (as in the above Circle)?
Define a
"fake" constant property? How to define it? Or has someone a elegant
strategy?

Thanks in advance!!

Never underestimate the power of GUID's

=)

- Michael S
 
G

Guest

Maybe a little bit more explanation about GUID's or a example could help me
not to underestimate them! ;-)
 
G

Guest

Thanks a lot for your help!

Lebesgue said:
Patrick Hertzog said:
Maybe a little bit more explanation about GUID's or a example could help me
not to underestimate them! ;-)

"Michael S" wrote:

Maybe a simple google search would help you
http://msdn.microsoft.com/library/d...ref/html/frlrfsystemguidclassnewguidtopic.asp

Guid is an absolute unique identifier

[C#]
public static Guid NewGuid();

use
this.myGuid = Guid.NewGuid();

and use Guid's hashcode for hashing your objects
 
J

Jay B. Harlow [MVP - Outlook]

Patrick.
In addition to the other comments:

| Microsoft states the following: "The hash function must return exactly the
| same value regardless of any changes that are made to the object". It
means

If your object is going to be used as a Key in a Hashtable, then Equals &
GetHashCode need to be based on immutable fields as the above suggests, If
they are based on mutable fields, then Hashtable will not work as expected.

Normally mutable objects (such as your "Circle" example) are not good
candidates for keys in Hashtables. I have used mutable objects as keys in
Hashtables, however the object raised Changing & Changed events to let the
DictionaryBase collection know that the key values (Equals & GetHashCode)
were changing allowing the collection to remove the old key & add the new
key...

Note "mutable objects" above is referring to objects where Equals &
GetHashCode are based on mutable fields.

Hope this helps
Jay

message | I've an issue when overriding GetHashCode methods. For instance, an
| hypothetical Circle object may have its hashcode defined as x ^ y ^
diameter.
| This works fine as long as the object is not modified (otherwise it
doesn't
| work).
|
| Microsoft states the following: "The hash function must return exactly the
| same value regardless of any changes that are made to the object". It
means
| that you should base your hashcode on properties that will not change. How
to
| proceed when all the properties can change (as in the above Circle)?
Define a
| "fake" constant property? How to define it? Or has someone a elegant
strategy?
|
| Thanks in advance!!
 
C

cody

When Circle is a class and not a struct you do not have to override
GetHashCode() because the default implementation will already hash using the
object's address which won't change.
 
J

Jon Skeet [C# MVP]

Lebesgue said:
Patrick Hertzog said:
Maybe a little bit more explanation about GUID's or a example could help me
not to underestimate them! ;-)

"Michael S" wrote:

Maybe a simple google search would help you
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpre
f/html/frlrfsystemguidclassnewguidtopic.asp

Guid is an absolute unique identifier

[C#]
public static Guid NewGuid();

use
this.myGuid = Guid.NewGuid();

and use Guid's hashcode for hashing your objects

But that way you end up with two different but equal objects having a
different hashcode, at which point you might as well not bother
overriding GetHashCode at all.
 
J

Jon Skeet [C# MVP]

cody said:
When Circle is a class and not a struct you do not have to override
GetHashCode() because the default implementation will already hash using the
object's address which won't change.

But if you're overriding Equals, you have to override GetHashCode to
match it if you want to be able to find an equal circle in a hash
table.
 
J

Jon Skeet [C# MVP]

Jay B. Harlow said:
| Microsoft states the following: "The hash function must return exactly the
| same value regardless of any changes that are made to the object". It
means

If your object is going to be used as a Key in a Hashtable, then Equals &
GetHashCode need to be based on immutable fields as the above suggests, If
they are based on mutable fields, then Hashtable will not work as expected.

It will, so long as the object doesn't change after it's put in the
Hashtable. This is actually a fairly common situation - create an
object, set it up after construction, then after that it doesn't
change.

I think the contract for GetHashCode is unfortunately worded,
personally.
 
B

Bruce Wood

Normally mutable objects (such as your "Circle" example) are not good
candidates for keys in Hashtables.

I disagree.

The problem that Patrick is facing here is one of semantics. That is,
what exactly is his hypothetical circle object in business terms, and
what does that imply about its identity, and about hashing it.

I see three possibilities:

1. The object (such as a circle) is what I would consider a value type.
Talking about a particular instance as having an identity different
from other instances does not make sense. For example, talking about
"this particular integer value 5" versus "that integer value 5 over
there" doesn't ring true. The value 5 is the value 5, and it makes no
sense to put it in a hash table. One could design a circle in the same
way: "this is a circle of radius 5, and it makes no sense to talk about
'this circle of radius 5' versus 'that circle of radius 5'." A value
type is typically a property of some other thing that has an identity;
it has no identity of its own, so you would hash on the identity of the
owner object.

2. The object has a unique identity. For example, a particular circle
that the user has drawn at particular coordinates with a partiuclar
colour. This is a case in which you want to assign the object a UID
that has nothing to do with its radius, location, or colour, because no
matter what happens to the circle, you want to clearly distinguish
between this circle and that other circle. Even if the user drew them
at the same location with the same radius and same colour, thay are
distinct objects.

3. You may wish to hash the second type of circle (the one with a clear
identity) by location, or some such thing, for lookup purposes. It is
in this case that you are hashing on mutable properties, and you need
to adopt a smart system such as the one that Jay outlined in order to
manage the lookup table as the circle's properties change. However, the
hash table is a convenience measure, not a hash on identity, and there
may be other ways to get the same effect without the complexity of
managing mutable hash keys.

So, you have to ask yourself:

1. Does the object I'm working with have an identity? Does it make
sense to distinguish between two otherwise identical objects because
they represent real world things that are dinstinct even if all of
their qualities are the same?

2. Am I hashing on identity, or as a convenient lookup on some quality
of the object that may change? If it's the latter, is there another way
to get the same convenience without having to worry about hashing on
mutable keys? If it's the former, and the object has no obviously
unique, immutable data on which to base a hash key, then you probably
need a UID.
 
M

Michael S

Thanks for coming to the rescue Bruce.
That was an excellent post! (.. as always...)


My regards
- Michael S
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top