Troelsen in his book, advises to override the class's ToString() method (the redefined version returns a string from the entire class fields using a space), and then in the GetHashCode method, call this.ToString().GetHashCode() .

Somewhere I read criticism of such an implementation, for example, a call to ToString () will generate garbage.

Is it true that she is not very good?

What can be alternatives?

  • five
    GetHashCode(){return GetRuStackOverflow();} . - user207618
  • one
    @Other, do not understand what you mean? - Umed
  • 3
    @Umed, there used to be a HashCode site, which became RuStackOverflow . The irony :) - user207618
  • @Other, very thin: D - Umed

2 answers 2

The problem with the string is that GetHashCode() can be called very often , many thousands of times per second. For example, when searching for an element in HashSet<T> or searching for a key in Dictionary<K, V> , each search element has a hashcode. If a temporary string is created each time, no one outside the method has the necessary string, then the garbage collector will have to clear them.

Therefore, the GetHashCode function should be as fast as possible and not create additional objects.

Regarding how it is better to consider hashcode, I would advise a little altered code from the @Umed response:

 public override int GetHashCode() { unchecked { int hash = 17; hash = hash * 23 + field1.GetHashCode(); // для поля типа-значения, например int hash = hash * 23 + field2.GetHashCode(); // то же самое if (field3 != null) // а это для поля ссылочного типа hash = hash * 23 + field3.GetHashCode(); return hash; } } 

Instead of 17 and 23, you can take other different prime numbers.


More on the topic: Why when overriding Equals, it is advised to also override GetHashCode .

  • Yes, your option will be more understandable than mine)) - Umed
  • Is multiplication by 23 to uniquely identify a class among other types? - iluxa1810
  • @ iluxa1810: No, it’s more likely that hashcodes are better mixed. If you simply add hashcodes, for example, then Point(1, 0) and Point(0, 1) will have the same codes. And this is bad, hash codes should be as different as possible. - VladD
  • one
    @VladD only with this approach - calculation of hashcode across all fields - the very meaning of GetHashCode is lost as a quick pre-check of Equals. Because for the same Point it is much easier and faster to compare the objects themselves than to calculate the cunning hashcode with arithmetic operations. Those. Return x.GetHashCode () can be more efficient than magic with prime numbers. - PashaPash
  • @PashaPash: Well, yes, the guidelines seem to even explicitly warn against using GetHashCode to pre-test equality. And x.GetHadhCode() degrades the distribution in the hash table. - VladD

Alternatively, you can count it as the sum of the hashes of its fields:

 public override int GetHashCode() { int result; uncheked { // если поле ссылочного типа, // то необходима проверка на null // если field1 будет null, то подставится 0 result = this.field1?.GetHashCode() ?? 0; result += this.field2?.GetHashCode() ?? 0; //... result += this.fieldN.GetHashCode(); } return result; } 

Or through the creation of an anonymous class ( peeped in English SO ):

 public override int GetHashCode() { return new { this.field1, this.field2, /*... ,*/ this.fieldN }.GetHashCode(); } 

This option also works fairly quickly, but with the exception that each call generates an anonymous class.

There you can see the answer of John Skit . He set up an algorithm with the choice of two random constants (they do not change, random - because you need to come up with them once) and calculate the hash as follows:

 public override int GetHashCode() { unchecked { int hash = 17; // если поле ссылочного типа, // то необходима проверка на null hash = hash * 23 + field1?.GetHashCode() ?? 0; // если это, например, int, то проверка ни к чему hash = hash * 23 + field3.GetHashCode(); return hash; } } 

I added a check for null from myself, about which he writes there in the answer

I advise you to follow the link and see that there are many useful things written there.

  • 2
    Well, the variant with an anonymous class also creates an object on the heap, that is, it loads the garbage collector, as does the variant with a string. - VladD
  • @VladD, alas, this is his minus, but knowing it is useful, I think. But he also brought his own primitive version and the one that John suggested. :) - Umed
  • I have not compiled your last example :-( - VladD
  • @VladD, corrected, did not consider what for reference types ?. returns not zero, but null - Umed