Short question
How to implement GetHashCode
for an Array
.
Details
I have an object that overrides Equals
, checking that:
this.array[n] == otherObject.array[n]
for all n
in array
.
Naturally I should implement the complementary GetHashCode
.
I was wondering if there is .NET way to do this, or if I should implement my own, something like
hash = hash ^ array[n]
Clarification
My object contains an array, and I'm interested on GetHashCode for the elements of the array. My code for array equivalence is for example only - like my question says but maybe I wasn't clear, I'm interested in GetHashCode
(not Equals
). I say I naturally should implement the complementary GetHashCode
because it is a requirement of .NET to implement this once Equals
is overridden (for Dictionary
etc. to function correctly). Thanks.
Python Hashing (Hash tables and hashlib) While an array can be used to construct hash tables, array indexes its elements using integers. However, if we want to store data and use keys other than integer, such as 'string', we may want to use dictionary. Dictionaries in Python are implemented using hash tables.
A Hash Table in C/C++ (Associative array) is a data structure that maps keys to values. This uses a hash function to compute indexes for a key. Based on the Hash Table index, we can store the value at the appropriate location.
Generally you create an array called "buckets" that contain the key and value, with an optional pointer to create a linked list. When you access the hash table with a key, you process the key with a custom hash function which will return an integer.
A hash function maps each key to an integer in the range [0, N -1], where N is the capacity of the bucket array for the hash table. The main idea is to use the hash value, h(k), as an index into our bucket array, A, instead of the key k (which is most likely inappropriate for use as a bucket array index).
To compute a hash code using the elements of an array, you can cast the array to IStructuralEquatable and then call the GetHashCode(IEqualityComparer) method, passing a comparer for the type of elements in the array.
(The cast is necessary because the Array class implements the method explicitly.)
For example, if your object has an int
array, then you can implement GetHashCode like this:
public override int GetHashCode() { return ((IStructuralEquatable)this.array).GetHashCode(EqualityComparer<int>.Default); }
In case you're curious, here's how the Array class implements the GetHashCode method (from the Reference Source):
internal static int CombineHashCodes(int h1, int h2) { return (((h1 << 5) + h1) ^ h2); } int IStructuralEquatable.GetHashCode(IEqualityComparer comparer) { if (comparer == null) throw new ArgumentNullException("comparer"); Contract.EndContractBlock(); int ret = 0; for (int i = (this.Length >= 8 ? this.Length - 8 : 0); i < this.Length; i++) { ret = CombineHashCodes(ret, comparer.GetHashCode(GetValue(i))); } return ret; }
As you can see, the current implementation only uses the last eight elements of the array.
It depends on what you want ...
One option as Michael answered above is to have a hashcode based on the array elements. This will be in line with your Equals value semantics. However because "As a guideline, the hash of an object must be the same over the object's entire lifetime" you will have to ensure your array does not change after getting its hashcode. To have a non immutable container with a demand that it never changes sounds error prone to me.
Your other (IMO better option) is to switch to an immutable container (ie ImmutableArray) then a value-based hashcode makes sense. You can either use IStructuralEquatable
as above or more generally:
public override GetHashCode() =>
Value.Aggregate(0, (total, next) => HashCode.Combine(total, next));
which will work for other immutable collections as well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With