473,769 Members | 2,377 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Generic GetHashCode method

I'm trying to write a generic method to generate Hashcodes but am having some
problems with (generic) collections. Here is the code of my method:

public static int GetHashCode(obj ect input)
{
try
{
Type objectType = input.GetType() ;
PropertyInfo[] properties = objectType.GetP roperties();

int totalHashCode = 7;

foreach (PropertyInfo property in properties)
{
// Reset hashcode
int hashcode = 0;

// Get property value
object value = property.GetVal ue(input, null);

// Invoke GetHashCode method on property
if (property.Prope rtyType.IsValue Type || value !=
null)
{

int.TryParse(pr operty.Property Type.InvokeMemb er("GetHashCode ",
BindingFlags.De fault | BindingFlags.In vokeMethod, null, value, null,
CultureInfo.Inv ariantCulture). ToString(), out hashcode);
}

totalHashCode ^= hashcode;
}
return totalHashCode;
}
catch(Exception )
{
// Handle exception
return 0;
}
}

public class Customer{
public Customer(){}
public string Name{get{return "Mr Blobby";}}
public string Telephone{get{r eturn "999";}}
}

public class CustomerCollect ion : List<Customer>
{
public CustomerCollect ion(){}
}

The problem I am having is that this method doesn't really take into account
objects which are(generic) collections. eg.. (excusing my simplicity) the
Customer class would work but the Customer Collection wouldn't. Can anyone
give me some pointers to improve this? Cheers in advance for any tips!
May 22 '06 #1
5 2284
Metaman <ma****@nospam. nospam.com> wrote:
I'm trying to write a generic method to generate Hashcodes but am having some
problems with (generic) collections. Here is the code of my method:
Normally, one overrides the GetHashCode() method to provide the hashcode
for an object.

It would be clearer if you described your algorithm for generating this
hashcode. It appears that you are iterating through all the properties
of an object and getting the hashcode of each property, and xoring them
together, and using that as the hashcode.

Because GetHashCode() is virtual and all objects in .NET have it, you
can invoke it directly. As far as I can make out, you could rewrite your
method like this:

---8<---
public static int GetHashCode(obj ect value)
{
if (value == null)
return 0;

int result = 0;
foreach (PropertyInfo prop in value.GetType() .GetProperties(
BindingFlags.In stance | BindingFlags.Pu blic))
{
if (prop.GetIndexP arameters().Len gth == 0)
{
object propValue = prop.GetValue(v alue, null);
if (propValue != null)
result ^= propValue.GetHa shCode();
}
}
return result;
}
--->8---

However, I don't think you should do this. I'll explain below.
public class Customer{
public Customer(){}
public string Name{get{return "Mr Blobby";}}
public string Telephone{get{r eturn "999";}}
}
Why don't you override the GetHashCode() method instead?
The problem I am having is that this method doesn't really take into account
objects which are(generic) collections. eg.. (excusing my simplicity) the
Customer class would work but the Customer Collection wouldn't. Can anyone
give me some pointers to improve this? Cheers in advance for any tips!


What you are describing is a GetHashCode() which iterates through an
entire list, and enumerates all the properties of every object in the
list, all to produce a single hash code.

Hash codes are used to insert and retrieve values into and from data
structures which use hash codes, usually Dictionary<,> or Hashtable. One
of the most important concerns in writing a hash function is that it
should be fast.

With the deep definition of equality that you are using, these hash
tables will be expensive for inserts and expensive for lookups.

-- Barry

--
http://barrkel.blogspot.com/
May 22 '06 #2
Thanks for your reply Barry. It slipped my mind that GetHashCode method is on
the base object as well so that makes things a little easier. The reason that
I am writing this function is that I have a number of objects that contain
quite a lot of properties. I need a reliable way of comparing two objects of
the same type to see if they are the same. Even if only one of their
properties differs slightly I need to be made aware of it. After doing some
testing the only way that seemed to work reliably was to Xor the hashcodes of
each property together. The problem with this is that for each object I then
need to override the GetHashcode method and write in all the properties
(which can be slow and unmaintainable if there is 30 properties or so)

eg..

public override int GetHashCode()
{
int result = Global.HashCode Multiplier;
result ^= ( Name.GetHashCod e() ^
Street1.GetHash Code() ^
Telephone.GetHa shCode() );
return result;
}

so I thought that an alternative would be to write a generic function to
handle this and then just override the GetHashCode method for each object as
follows:

public override int GetHashCode()
{
return ObjectHelper.Ge tHashCode(this) ;
}

I appreciate that this is not the most effiecient way of checking whether
objects are the same but not sure what a better way of generating a hashcode
could be.

P.S. I actually override the Equals method first which checks the easy
things (makes sure that they are the same type etc..)

"Barry Kelly" wrote:
Metaman <ma****@nospam. nospam.com> wrote:
I'm trying to write a generic method to generate Hashcodes but am having some
problems with (generic) collections. Here is the code of my method:


Normally, one overrides the GetHashCode() method to provide the hashcode
for an object.

It would be clearer if you described your algorithm for generating this
hashcode. It appears that you are iterating through all the properties
of an object and getting the hashcode of each property, and xoring them
together, and using that as the hashcode.

Because GetHashCode() is virtual and all objects in .NET have it, you
can invoke it directly. As far as I can make out, you could rewrite your
method like this:

---8<---
public static int GetHashCode(obj ect value)
{
if (value == null)
return 0;

int result = 0;
foreach (PropertyInfo prop in value.GetType() .GetProperties(
BindingFlags.In stance | BindingFlags.Pu blic))
{
if (prop.GetIndexP arameters().Len gth == 0)
{
object propValue = prop.GetValue(v alue, null);
if (propValue != null)
result ^= propValue.GetHa shCode();
}
}
return result;
}
--->8---

However, I don't think you should do this. I'll explain below.
public class Customer{
public Customer(){}
public string Name{get{return "Mr Blobby";}}
public string Telephone{get{r eturn "999";}}
}


Why don't you override the GetHashCode() method instead?
The problem I am having is that this method doesn't really take into account
objects which are(generic) collections. eg.. (excusing my simplicity) the
Customer class would work but the Customer Collection wouldn't. Can anyone
give me some pointers to improve this? Cheers in advance for any tips!


What you are describing is a GetHashCode() which iterates through an
entire list, and enumerates all the properties of every object in the
list, all to produce a single hash code.

Hash codes are used to insert and retrieve values into and from data
structures which use hash codes, usually Dictionary<,> or Hashtable. One
of the most important concerns in writing a hash function is that it
should be fast.

With the deep definition of equality that you are using, these hash
tables will be expensive for inserts and expensive for lookups.

-- Barry

--
http://barrkel.blogspot.com/

May 23 '06 #3


Metaman wrote:
Thanks for your reply Barry. It slipped my mind that GetHashCode method is on
the base object as well so that makes things a little easier. The reason that
I am writing this function is that I have a number of objects that contain
quite a lot of properties. I need a reliable way of comparing two objects of
the same type to see if they are the same. Even if only one of their
properties differs slightly I need to be made aware of it. After doing some
Then looking at the hash-codes won't be enough.

By convention:
x.Equals(y) => x.GetHashCode() == y.GetHashCode()
but
x.GetHashCode() == y.GetHashCode() =/> x.Equals(y)

If your hash-codes are intractible you may be able to argue equivalence
upto a certain acceptable error-margin, but really 2^32 is a very small
co-domain for an intractible hash.

If you wish to "fit into .NET" you should write an implementation of
IEqualityCompar er<T> that uses reflections on the properties and
(recursively) applies hashing/comparison to the objects.

Note that computing the hash-value and comparing those to "optimize"
comparison will probably be a lot slower than just doing the comparison
inline, and unless you rely on intractability of the hash you will need
to do the comparison anyway.
I appreciate that this is not the most effiecient way of checking whether
objects are the same but not sure what a better way of generating a hashcode
could be.
hashing is *not* equality.
P.S. I actually override the Equals method first which checks the easy
things (makes sure that they are the same type etc..)


If x.Equals(y) then it should definatly be the case that x.GetHashCode()
== y .GetHashCode(), not the other way around.

--
Helge
May 23 '06 #4
Hey Helge,

Thanks for your reply. I appreciate that as Hashcodes determined by a
GetHashcode method are only integer values there is a finite number of
results with collision a possibility. Part of the reason why I am using
hashcodes is that I need to calculate whether objects have changed when
exporting from another system. I store hashcodes in a database and then
compare the hashcode of the exported object with the value that has
previously been stored in the database.

Is there a better way of creating a hashcode of an object that will have
less collision than a GetHashCode integer?

I agree that for comparing two objects (rather than object vs hashcode -
above) implementing the IEqualityCompar er<T> would be better. I'm also aware
that hashing is *not* equality (see my overriden Equals method below).
Perhaps my wording was not correct.

public override bool Equals(object obj)
{
// Check that the parameter has value
if (obj == null) return false;

// Check that types are the same
if (GetType() != obj.GetType()) return false;

// safe because of the GetType check
Customer customer = (Customer)obj;

// Check if hash codes match (being the same does not guarantee
equality
// however if the hashcode are different then definitely not
equal)
if (! GetHashCode().E quals(customer. GetHashCode())) return false;

return true;
}
"Helge Jensen" wrote:


Metaman wrote:
Thanks for your reply Barry. It slipped my mind that GetHashCode method is on
the base object as well so that makes things a little easier. The reason that
I am writing this function is that I have a number of objects that contain
quite a lot of properties. I need a reliable way of comparing two objects of
the same type to see if they are the same. Even if only one of their
properties differs slightly I need to be made aware of it. After doing some


Then looking at the hash-codes won't be enough.

By convention:
x.Equals(y) => x.GetHashCode() == y.GetHashCode()
but
x.GetHashCode() == y.GetHashCode() =/> x.Equals(y)

If your hash-codes are intractible you may be able to argue equivalence
upto a certain acceptable error-margin, but really 2^32 is a very small
co-domain for an intractible hash.

If you wish to "fit into .NET" you should write an implementation of
IEqualityCompar er<T> that uses reflections on the properties and
(recursively) applies hashing/comparison to the objects.

Note that computing the hash-value and comparing those to "optimize"
comparison will probably be a lot slower than just doing the comparison
inline, and unless you rely on intractability of the hash you will need
to do the comparison anyway.
I appreciate that this is not the most effiecient way of checking whether
objects are the same but not sure what a better way of generating a hashcode
could be.


hashing is *not* equality.
P.S. I actually override the Equals method first which checks the easy
things (makes sure that they are the same type etc..)


If x.Equals(y) then it should definatly be the case that x.GetHashCode()
== y .GetHashCode(), not the other way around.

--
Helge

May 24 '06 #5


Metaman wrote:
Hey Helge,

Thanks for your reply. I appreciate that as Hashcodes determined by a
GetHashcode method are only integer values there is a finite number of
results with collision a possibility. Part of the reason why I am using
hashcodes is that I need to calculate whether objects have changed when
exporting from another system. I store hashcodes in a database and then
compare the hashcode of the exported object with the value that has
previously been stored in the database.
So, basically you *are* using your hash-function as an equality
relation? That is a useful technique, since you don't need to store the
original object, only the hash, to decide if anything has changed.

Unfortunately, it comes at a cost: the chance that the object is
different but has the same hash.

You may be willing to accept that risk, which is determined by the
quality of your hash-function and the size of the co-domain.

If your hash-function is perfect the chance of invalidly classifying an
object as unchanged will be 1/(2^32), which may be acceptable to you.

If your hash-function is worse than that, it may be *much* worse. If you
compare, not only to an "old" hash-value, but to a set of old values
chances of failure also increases dramatically.

You were using xor to combine hash'es, that means that any number of
occurrences of the same item modulo 2 will cancel out. As an example,
the objects { x=1; y=1 } and { x=2; y=2 } will collide. This may be a
*real* problem for you. Good hash-functions have a complicated structure
to try and prevent structural equivalence from generating hash-equivalence.
Is there a better way of creating a hashcode of an object that will have
less collision than a GetHashCode integer?
You expect to rely on GetHashCode() of each member right? and then
combine them in some way for a combined hash. I would suggest ordering
the traversal and applying a cryptographic hash (for example one of the
SHA variants) to the contanenation of the GetHashCode()'e s.
public override bool Equals(object obj)
{
// Check that the parameter has value
if (obj == null) return false;
You may wish to:

if ( Object.Referenc eEquals(this,ob j) )
return true;

depending on the expected self vs. non-self. comparison ratio.
// Check that types are the same
if (GetType() != obj.GetType()) return false;
So inherited implementations , without member-variables are considered
non-equal, even if all members are equal?

Test-implementations also? :)
// safe because of the GetType check
Customer customer = (Customer)obj;

// Check if hash codes match (being the same does not guarantee
equality
// however if the hashcode are different then definitely not
equal)
if (! GetHashCode().E quals(customer. GetHashCode())) return false;
So, you really need:

// Check every part sequentially
return this.x == customer.x && this.y == customer.y && ...;

or you are in fact relying on the hash-function for equality.
return true;
}


--
Helge
May 24 '06 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

7
6576
by: Avin Patel | last post by:
Hi I have question for GetHashCode() function, Is it correct in following code or there is more efficient way to implement GetHashCode() function class IntArray public int data public override int GetHashCode() int hash = 0 for (int i = 0; i < data.Length; i++
2
2378
by: One Handed Man [ OHM# ] | last post by:
The help for the .NET Framework Class Library tells us that the Object.GetHashCode() Method does not guarantee uniqueness' or consistency and that overriding this and the Equals method is a good idea. It also tells us that using the XOR functions on two or more Fields or Properties is an acceptable way to achieve this. What do you guys think is the best approach to this given that generating a hashcode should be fast as well as consistant....
12
1861
by: Elhanan | last post by:
hi.. i wanted to build a Dictionary Classs that will load my own class called letter, i understood that i implement the IEquatable interface's equles method that then the dictionary would use that inorder to compare the keys, so i went ahead the implented it in the LETTER class so letter would provice it's own means for comparison, but the dictionary ignored it only when i created a new class, called it letterkey ,had it implement
3
3680
by: kim.nolsoee | last post by:
Hi I want to use the Dictionary Classs that will load my own class called KeyClass used as TKey. Here is the code: public class Dictionary { public static void Main()
4
392
by: Andrew Robinson | last post by:
I have a class that has three properties: two of type int and one of type string. Is this the best method when overriding the GetHashCode() ? I am guessing not... any thing better? public override int GetHashCode() { string hash = craneCounterweightID.ToString() + ":" + trailerID.ToString() + ":" + craneConfigurationTypeCode; return hash.GetHashCode();
5
1868
by: Ethan Strauss | last post by:
Hi, I have just started using Generic Collections for .Net 2.0 and so far they are working very nicely for me. But, I do have a couple of questions. If I have a Generic collection which has a type which is a reference type, is there a way to get Collection.ContainsKey(RefKey) and Collection to work with different instances of equal keys? For example, I have defined a class of "codon" and I have made a dictionary private...
6
2922
by: Andrus | last post by:
I need to create generic table field level cache. Table primary key (PrimaryKeyStructType) can be int, string or struct containing int and string fields. FieldName contains table field name to be cached. Remove() should remove table row from cache. Row is identified by table primary key. Trying compile class causes error Operator '==' cannot be applied to operands of type
28
3787
by: Tony Johansson | last post by:
Hello! I can't figure out what point it is to use GetHashCode. I know that this GetHashCode is used for obtaining a unique integer value. Can somebody give me an example that prove the usefulness of this GetHashCode or it it of no use at all? A mean that if I get an integer from current time in some way what should I use it for?
1
2459
by: raylopez99 | last post by:
Here is an example of a home grown generic class, representing a pair of values. Adapted from Jon Skeet's book "C# In Depth". The generic class is "sealed" for some reason (I think for performance) so you cannot derive from it, but that's optional. The main thing in this example is to show the right format for using these generic classes, which was not present in the code snippet in Skeet's book. Does anybody know why the .Equals...
0
9589
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
10050
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
9999
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8876
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
6675
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5310
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5448
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3967
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
3
2815
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.