I have writing a method which needs to be able to take an arbitrary number of fields of data, combine them in some way into a hashable object, then hash this object in a dictionary for later lookup.
So far the best algorithm I’ve come up with is to take ToHashCode() for each field, then join the resulting hashcodes into a string using some kind of separator character (such as “|”), and then use this resulting string as a unique key for the dictionary.
Does anyone know of a more efficient way to do this? I was thinking perhaps there is some way to take the hashcode of each field, and do some mathematical operation to combine them into a unique hashable number, but this was just a guess.
Thanks for any help.
EDIT:
I think people may be confused as to what exactly I mean. Tuples will not work in this situation because I need an arbitrary number of fields to be combined into a single hashable object. The number of fields is only known at runtime, not at design time.
The other solution given about combining all the hashcodes mathematically into a new hashcode also will not work, because I need an object that can be used as a key into a Dictionary. Using a hashcode as a key into a Dictionary is very dangerous I believe.
EDIT 2:
After thinking about this some more I think my original solution is not a good one. In the limiting case where there is a single field, my solution has degenerated into putting a string version of the hashcode into a Dictionary.
I think perhaps a better solution is to make a new type which takes an enumerable in its constructor, and implements GetHashCode(). The GetHashCode() function would then loop through each value of the enumerable and perform the usual type of accumulator logic in hash code functions. This way, the object can be stuck into a dictionary, hashset, etc. and behave as you would expect.
The key here was realizing that any arbitrarily sized collection of objects can be hashed by simply treating it as an IEnumerable whose hashcode depends on the contents of the enumeration.
To do this I simply made a ValueAwareEnumerable class that implements IEnumerable. This class takes an enumerable in its only constructor. It then overrides GetHashCode() and Equals() so that they depend on the contents of the enumerable. The GetHashCode method is simply:
and Equals:
The caveat here is that it depends on the order of the enumerable. If needed, it’s possible to make it order-independent by simply making GetHashCode() and Equals() sort the enumerable before iterating through it.
To finish it off, just add in an extension method somewhere for good measure:
And you can do things like:
This will work for any data type, and even mixed data types, if you treat them as an
IEnumerable<Object>.