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! 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/
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/
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
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
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 This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
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++
|
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....
|
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
|
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()
|
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();
| |
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...
|
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
|
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?
|
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...
|
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...
|
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...
| |
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,...
|
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...
|
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();...
|
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...
|
by: adsilva |
last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
|
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
| |
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...
| |