Skip to main content
Code Review

Return to Question

replaced http://stackoverflow.com/ with https://stackoverflow.com/
Source Link

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;
}
  1. Are there any problems with this code?

  2. 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 bools 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;
}
  1. Are there any problems with this code?

  2. 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 bools 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;
}
  1. Are there any problems with this code?

  2. 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 bools for example (since bool has only 2 hash values in .NET: 1 and 0).

deleted 968 characters in body
Source Link
Jamal
  • 35.2k
  • 13
  • 134
  • 238

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.

  1. Are there any problems with this code?

  2. 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 bools 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 bools 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;
}
  1. Are there any problems with this code?

  2. 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 bools for example (since bool has only 2 hash values in .NET: 1 and 0).

please review is not needed
Link
Caridorc
  • 28k
  • 7
  • 54
  • 137

Please criticize composite Composite GetHashCode function

added 1057 characters in body
Source Link
Mike
  • 121
  • 3
Loading
Source Link
Mike
  • 121
  • 3
Loading
lang-cs

AltStyle によって変換されたページ (->オリジナル) /