-1

Let's say I have a class with Name and Type properties, If I store the hashcode as below in a database, can I compare this hashcode in another process which has same name and type?

will the hashcode be same?

Name.ToLower().GetHashCode() + Type.ToLower().GetHashCode();
Igor
  • 60,821
  • 10
  • 100
  • 175
Chandu
  • 31
  • 3
  • 2
    What's wrong with just storing the actual value? – gunr2171 Nov 15 '21 at 18:00
  • 5
    No, definitely NOT guaranteed. Never do that. [Read the "Warning" box in the documentation.](https://learn.microsoft.com/en-us/dotnet/api/system.object.gethashcode?view=net-5.0) The top item is literally `Do not serialize hash code values or store them in databases.` – Matthew Watson Nov 15 '21 at 18:01
  • There is nothing wrong, design was demanding this. Please let me know if it will work – Chandu Nov 15 '21 at 18:03
  • 1
    Don't store hash codes returned by `GetHashCode`. The underlying implementation may change over time. During the lifetime of a process, it must return the same hash code for the same value or else dictionaries would break (for example). But between process lifetimes, the upgrade of the runtime (or a library) could change the algorithm and result in different hash codes and what's in your database wouldn't match. – madreflection Nov 15 '21 at 18:03
  • No, they will not be the same. As others have pointed out, changes to .NET Framework or .NET Core or .NET version may change this, both major and minor versions, may cause a change. Because they did document that they're allowed to change it, **they're allowed to change it**. Not only that, just running your program multiple times will likely generate different hashcode because for security reasons .NET now creates unique hashcode on each program execution. So no, they will not be the same. – Lasse V. Karlsen Nov 15 '21 at 18:07
  • 1
    `design was demanding this` ← What does that mean? Is that a person? What was the *exact* requirement? Maybe it was to use hash codes but not necessarily `GetHashCode()`? In that case there are many different hash implementations that you could use. – Igor Nov 15 '21 at 18:07
  • 1
    In .NET Core 3.1, .NET 5 and .NET 6, running the same program twice, with something as simple as `Console.WriteLine("Test".GetHashCode());` will produce different outputs. – Lasse V. Karlsen Nov 15 '21 at 18:09
  • What are the types of `Name` and `Type`? Does your class make them immutable (so that their values never change)? Do you implement the `GetHashCode` overrides for the types of `Name` and `Type`. Make sure you read @matthew's note about the Warning – Flydog57 Nov 15 '21 at 18:09
  • 1
    You *can* implement your own hashcode calculation, in which case you and your team will have a say in when it should change and how. – Lasse V. Karlsen Nov 15 '21 at 18:12

1 Answers1

0

No, they will not, but look towards the end here for a more durable solution that might fit your needs.

First, there's the warning in the documentation:

Warning
A hash code is intended for efficient insertion and lookup in collections that are based on a hash table. A hash code is not a permanent value. For this reason:

  • Do not serialize hash code values or store them in databases.
  • Do not use the hash code as the key to retrieve an object from a keyed collection.
  • Do not send hash codes across application domains or processes. In some cases, hash codes may be computed on a per-process or per-application domain basis.
    ...

There's more in the warning but the last one illustrates a rather good point.

Simply create a small program with this code:

Console.WriteLine("Test".GetHashCode());

Then run this for .NET Core 3.1, .NET 5 or .NET 6, repeatedly.

You'll get different values

So to answer your question, no, they will not stay the same.

However, you can roll your own implementation. Here's a rather simple implementation of a hashcode function for strings that would only change if you change it yourself:

public static int SemiStableHashCode(string input)
{
    unchecked
    {
        byte[] bytes = Encoding.UTF8.GetBytes(input.Normalize(NormalizationForm.FormKD));
        int result = 17;
        foreach (byte b in bytes)
            result = result * 23 + b;
        return result;
    }
}

Having said that, it just occurred to me that .NET 5 and 6 changed their Unicode support to use ICU instead of Win32, so who knows how "stable" my method is.

Lasse V. Karlsen
  • 380,855
  • 102
  • 628
  • 825