17

I just wasted few hours of debugging before realizing that contrary to .NET, in .NET Core, GetHashCode returns a different value every time you run your code. I totally understand the rationale for this. Relying on hash code values is a very bad idea (like serializing them). I even remember that internal builds of .NET at Microsoft (prior to Core) would change the behavior of GetHashCode for every build so that nobody gets too comfortable with it.

Having said all this, I’m currently debugging complex code that makes heavy use of GetHashCode. I know the bug is my own doing and has nothing to do with GetHashCode but each time I run it, it fails elsewhere. Very annoying. Is there a way to force GetHashCode to behave like in .NET (while I’m debugging) without having to write my own hash function and having to replace it everywhere in my code?

Franck Jeannin
  • 6,107
  • 3
  • 21
  • 33
  • 1
    Do you mean `String.GetHashCode()` or `Object.GetHashCode()`? I don't think you can influence the latter at all; it's always based on the object reference which is never more than pseudo-deterministic. The former is governed by `FEATURE_RANDOMIZED_STRING_HASHING` at compile time and by [``](https://msdn.microsoft.com/library/jj152924) at runtime -- but I have no idea if .NET Core respects the latter, just that it's definitely on by default. – Jeroen Mostert Dec 16 '16 at 12:00
  • To clarify, when I say "compile time", I mean at the time of compiling the *runtime*, not your own application. Defining `FEATURE_RANDOMIZED_STRING_HASHING` in your own code does nothing. But .NET Core being open source, you could always rebuild it if it comes to that. – Jeroen Mostert Dec 16 '16 at 12:15
  • My code is generic so, in effect it's object.GetHashCode() but in my exemple the object is a string so the hash code is based on the (immutable) string content. – Franck Jeannin Dec 16 '16 at 13:06

2 Answers2

2

According to docs only change of framework should change the hash result. I too stumbled upon this. My solution was to create my own hash algorithm. It just took a few minutes as I didn't need anything fancy.

private static int GetSimpleHash(string s)
{
    return s.Select(a => (int)a).Sum();
}

On a side note I have filed a bug for dotnet core 1.1. (string).GetHashCode() here.

Update

The hash can change due to framework or domain. This means that two subsequent runs of the same program can return different results.
Alas my bug report is moot and changed to a documentation update instead.

Update update

Documentation is updated to be a little bit more clear.

LosManos
  • 7,195
  • 6
  • 56
  • 107
  • 3
    Just chiming in here, the example hashcode LosManos has given is extremely problematic , in that it is extremely likely to give hash collisions. if for similicity we pretend that (int)a => 1, and (int)b =>2, etc, then "ab" and "c" will both have the hashcode of 3, for example. There are better hash code algorithms that avoid this issue. – Robert Christ Jul 11 '22 at 21:52
  • I borrowed from this: https://stackoverflow.com/a/67013015/1033684 – Rob Sedgwick Sep 29 '22 at 15:00
-4

The pragmatic solution I have found to get string.GetHashCode to return predicable values across multiple executions is simply to switch back to classic .NET (4.6). Since there is nothing .NET Core specific about my code, the only work I had to do was create a new project. I debugged my code under .NET 4.6, fixed the bug and switched back to Core.

Franck Jeannin
  • 6,107
  • 3
  • 21
  • 33