views:

302

answers:

3

Hello,

i have some questions about the HashCode of immutable types.

  • May i "pre"-generate the HashCode of an immutable type in the constructor or are there any reason not do that?
  • Should i always generate the Hashcode again, when the method GetHashCode() is called?

Here´s a sample class :

    public class Id  {

        private readonly object _value;

        private readonly int _hash = -1;


        public Id( object value ) {
          _value = value;
          _hash = ( int ) ( 7 * value.GetType().GetHashCode() + 7 + 7 * _value.GetHashCode() );
        }

        public object Value {
          get {
            return _value;
          }
        }

        public override int GetHashCode() {
          return _hash;
        }

        public override bool Equals( object obj ) {
          Id other = obj as Id;

          if ( other == null ) {
            return false;
          }

          return this.GetHashCode() == other.GetHashCode();
        }
        }
A: 

Reason not to pregenerate: it slows down object creation.

Reason to always regenerate: you save the storage needed to keep the hashcode around.

For the record, I'd probably precompute the hashcode and store it for immutable objects unless profiling showed me it was expensive and I wasn't accessing the value very often.

Hank Gay
+7  A: 

You may pregenerate the hashcode but why? Just generate it when needed (in GetHashCode) and then maybe store it - Most objects are never required to have a hash so it would just slow down the programm.

Should i always generate the Hashcode again, when the method GetHashCode() is called?

The hashcode of an immutable object should always be the same so it shouldn't have any effect whether you generate it again or store it except that storing increases the performance.

Note: You shouln't define Equals by comparing HashCodes - Two different object may have equal HashCodes (hash collsion).

Dario
+1  A: 

This really depends on the use-case.

Do you use the hash a lot? Then pregenerate it, because the object is immutable, calculating it every time would be unnecessary since the result is always the same.

Isn't the hash used a lot? Then don't pregenerate it, since it will slow down the program unnecessarily, calculating a hash that's likely not to be used.

A third (and best, in my opinion) option is to calculate the hash in GetHashCode and cache the result, calculating the hash only once and return this cached hash every time after that. This way, no time is spent calculating a hash when it's never used, nor is it calculated unnecessarily every time GetHashCode is called. Although this does mean memory is used to store the hash in the object.

JulianR