I've built a small library for comparing objects based on their members here (related SO question related SO question).
There's a need to compute hash function in order to conform to IEqualityComparer<T>
interface. In my case this function has to be computed based on the hash functions of members. So the main problem is how to compose them.
I use the following approach currently:
public int GetHashCode(T obj)
{
VerifyHaveMembersSetup();
if (TypeTester<T>.IsNull(obj))
{
return 0;
}
if (getHashCodeBehavior == GetHashCodeBehavior.Cache && cachedHashCode.HasValue)
{
return cachedHashCode.Value;
}
int hashCode = 0;
for (int i = 0; i < memberSetups.Count; ++i)
{
int leftShift = i % 32;
int rightShift = 32 - leftShift;
int memberHashCode = memberSetups[i].GetMemberHashCode(obj);
hashCode = hashCode ^ ((memberHashCode << leftShift) | (memberHashCode >> rightShift));
}
if (getHashCodeBehavior == GetHashCodeBehavior.ImmutableCheck
&& cachedHashCode.HasValue && cachedHashCode.Value != hashCode)
{
throw new InvalidOperationException("Hash code value changed");
}
cachedHashCode = hashCode;
return hashCode;
}
Are there any problems with this code?
I don't like the way many people implement composite functions I don't like the way many people implement composite functions. With multiplication and addition, significant bits are shifted away and are lost.
That's why I use bitshift operators <<
and >>
. Still I'm not completely sure how good would be a hash function generated such way. Especially when it's computed over small collection of memberSetups
of bool
s for example (since bool
has only 2 hash values in .NET: 1 and 0).
I've built a small library for comparing objects based on their members here (related SO question).
There's a need to compute hash function in order to conform to IEqualityComparer<T>
interface. In my case this function has to be computed based on the hash functions of members. So the main problem is how to compose them.
I use the following approach currently:
public int GetHashCode(T obj)
{
VerifyHaveMembersSetup();
if (TypeTester<T>.IsNull(obj))
{
return 0;
}
if (getHashCodeBehavior == GetHashCodeBehavior.Cache && cachedHashCode.HasValue)
{
return cachedHashCode.Value;
}
int hashCode = 0;
for (int i = 0; i < memberSetups.Count; ++i)
{
int leftShift = i % 32;
int rightShift = 32 - leftShift;
int memberHashCode = memberSetups[i].GetMemberHashCode(obj);
hashCode = hashCode ^ ((memberHashCode << leftShift) | (memberHashCode >> rightShift));
}
if (getHashCodeBehavior == GetHashCodeBehavior.ImmutableCheck
&& cachedHashCode.HasValue && cachedHashCode.Value != hashCode)
{
throw new InvalidOperationException("Hash code value changed");
}
cachedHashCode = hashCode;
return hashCode;
}
Are there any problems with this code?
I don't like the way many people implement composite functions. With multiplication and addition, significant bits are shifted away and are lost.
That's why I use bitshift operators <<
and >>
. Still I'm not completely sure how good would be a hash function generated such way. Especially when it's computed over small collection of memberSetups
of bool
s for example (since bool
has only 2 hash values in .NET: 1 and 0).
I've built a small library for comparing objects based on their members here (related SO question).
There's a need to compute hash function in order to conform to IEqualityComparer<T>
interface. In my case this function has to be computed based on the hash functions of members. So the main problem is how to compose them.
I use the following approach currently:
public int GetHashCode(T obj)
{
VerifyHaveMembersSetup();
if (TypeTester<T>.IsNull(obj))
{
return 0;
}
if (getHashCodeBehavior == GetHashCodeBehavior.Cache && cachedHashCode.HasValue)
{
return cachedHashCode.Value;
}
int hashCode = 0;
for (int i = 0; i < memberSetups.Count; ++i)
{
int leftShift = i % 32;
int rightShift = 32 - leftShift;
int memberHashCode = memberSetups[i].GetMemberHashCode(obj);
hashCode = hashCode ^ ((memberHashCode << leftShift) | (memberHashCode >> rightShift));
}
if (getHashCodeBehavior == GetHashCodeBehavior.ImmutableCheck
&& cachedHashCode.HasValue && cachedHashCode.Value != hashCode)
{
throw new InvalidOperationException("Hash code value changed");
}
cachedHashCode = hashCode;
return hashCode;
}
Are there any problems with this code?
I don't like the way many people implement composite functions. With multiplication and addition, significant bits are shifted away and are lost.
That's why I use bitshift operators <<
and >>
. Still I'm not completely sure how good would be a hash function generated such way. Especially when it's computed over small collection of memberSetups
of bool
s for example (since bool
has only 2 hash values in .NET: 1 and 0).
I've built a small library for comparing objects based on their members https://github.com/alabax/YetAnotherEqualityComparerhere (related SO question). There's
There's a need to compute hash function in order to conform to IEqualityComparer<T>
interface. In my case this function has to be computed based on the hash functions of members. So the main problem is how to compose them.
I use the following approach currently:
public int GetHashCode(T obj)
{
VerifyHaveMembersSetup();
if (TypeTester<T>.IsNull(obj))
{
return 0;
}
if (getHashCodeBehavior == GetHashCodeBehavior.Cache && cachedHashCode.HasValue)
{
return cachedHashCode.Value;
}
int hashCode = 0;
for (int i = 0; i < memberSetups.Count; ++i)
{
int leftShift = i % 32;
int rightShift = 32 - leftShift;
int memberHashCode = memberSetups[i].GetMemberHashCode(obj);
hashCode = hashCode ^ ((memberHashCode << leftShift) | (memberHashCode >> rightShift));
}
if (getHashCodeBehavior == GetHashCodeBehavior.ImmutableCheck
&& cachedHashCode.HasValue && cachedHashCode.Value != hashCode)
{
throw new InvalidOperationException("Hash code value changed");
}
cachedHashCode = hashCode;
return hashCode;
}
First of all are there any problems with this code?
Second, I don't like the way many people implement composite functions http://stackoverflow.com/a/263416/484050 . Because with multiplications and additions significant bits are shifted away and are lost.
Are there any problems with this code?
I don't like the way many people implement composite functions . With multiplication and addition, significant bits are shifted away and are lost.
That's why I use bitshift operators <<
and >>
. Still I'm not completely sure how good would be a hash function generated such way. Especially when it's computed over small collection of memberSetups
of bool
s for example (since bool
has only 2 hash values in .NET: 1 and 0).
UPDATE: Now I'm using FNV-1a hash function and the code is looking like this:
private const int HashBasis = unchecked((int)2166136261);
private const int HashPrime = 16777619;
int hashCode = HashBasis;
for (int i = 0; i < memberSetups.Count; ++i)
{
int memberHashCode = memberSetups[i].GetMemberHashCode(obj);
unchecked
{
hashCode = (hashCode ^ (memberHashCode & 0xFF)) * HashPrime;
hashCode = (hashCode ^ ((memberHashCode >> 8) & 0xFF)) * HashPrime;
hashCode = (hashCode ^ ((memberHashCode >> 16) & 0xFF)) * HashPrime;
hashCode = (hashCode ^ ((memberHashCode >> 24) & 0xFF)) * HashPrime;
}
}
Does it make more sense?
I've built a small library for comparing objects based on their members https://github.com/alabax/YetAnotherEqualityComparer (related SO question).
There's a need to compute hash function in order to conform to IEqualityComparer<T>
interface. In my case this function has to be computed based on the hash functions of members. So the main problem is how to compose them
I use the following approach currently
public int GetHashCode(T obj)
{
VerifyHaveMembersSetup();
if (TypeTester<T>.IsNull(obj))
{
return 0;
}
if (getHashCodeBehavior == GetHashCodeBehavior.Cache && cachedHashCode.HasValue)
{
return cachedHashCode.Value;
}
int hashCode = 0;
for (int i = 0; i < memberSetups.Count; ++i)
{
int leftShift = i % 32;
int rightShift = 32 - leftShift;
int memberHashCode = memberSetups[i].GetMemberHashCode(obj);
hashCode = hashCode ^ ((memberHashCode << leftShift) | (memberHashCode >> rightShift));
}
if (getHashCodeBehavior == GetHashCodeBehavior.ImmutableCheck
&& cachedHashCode.HasValue && cachedHashCode.Value != hashCode)
{
throw new InvalidOperationException("Hash code value changed");
}
cachedHashCode = hashCode;
return hashCode;
}
First of all are there any problems with this code?
Second, I don't like the way many people implement composite functions http://stackoverflow.com/a/263416/484050 . Because with multiplications and additions significant bits are shifted away and are lost.
That's why I use bitshift operators <<
and >>
. Still I'm not completely sure how good would be a hash function generated such way. Especially when it's computed over small collection of memberSetups
of bool
s for example (since bool
has only 2 hash values in .NET: 1 and 0).
UPDATE: Now I'm using FNV-1a hash function and the code is looking like this:
private const int HashBasis = unchecked((int)2166136261);
private const int HashPrime = 16777619;
int hashCode = HashBasis;
for (int i = 0; i < memberSetups.Count; ++i)
{
int memberHashCode = memberSetups[i].GetMemberHashCode(obj);
unchecked
{
hashCode = (hashCode ^ (memberHashCode & 0xFF)) * HashPrime;
hashCode = (hashCode ^ ((memberHashCode >> 8) & 0xFF)) * HashPrime;
hashCode = (hashCode ^ ((memberHashCode >> 16) & 0xFF)) * HashPrime;
hashCode = (hashCode ^ ((memberHashCode >> 24) & 0xFF)) * HashPrime;
}
}
Does it make more sense?
I've built a small library for comparing objects based on their members here (related SO question).
There's a need to compute hash function in order to conform to IEqualityComparer<T>
interface. In my case this function has to be computed based on the hash functions of members. So the main problem is how to compose them.
I use the following approach currently:
public int GetHashCode(T obj)
{
VerifyHaveMembersSetup();
if (TypeTester<T>.IsNull(obj))
{
return 0;
}
if (getHashCodeBehavior == GetHashCodeBehavior.Cache && cachedHashCode.HasValue)
{
return cachedHashCode.Value;
}
int hashCode = 0;
for (int i = 0; i < memberSetups.Count; ++i)
{
int leftShift = i % 32;
int rightShift = 32 - leftShift;
int memberHashCode = memberSetups[i].GetMemberHashCode(obj);
hashCode = hashCode ^ ((memberHashCode << leftShift) | (memberHashCode >> rightShift));
}
if (getHashCodeBehavior == GetHashCodeBehavior.ImmutableCheck
&& cachedHashCode.HasValue && cachedHashCode.Value != hashCode)
{
throw new InvalidOperationException("Hash code value changed");
}
cachedHashCode = hashCode;
return hashCode;
}
Are there any problems with this code?
I don't like the way many people implement composite functions . With multiplication and addition, significant bits are shifted away and are lost.
That's why I use bitshift operators <<
and >>
. Still I'm not completely sure how good would be a hash function generated such way. Especially when it's computed over small collection of memberSetups
of bool
s for example (since bool
has only 2 hash values in .NET: 1 and 0).