I have to generate a unique "Hash" based upon an array of parameters. So far I've been using string builder to generate a unique string for every set of parameters, and then using GetHashCode()
for a unique int.
public static int SeedByParameters(params int[] parameters)
{
StringBuilder builder = new StringBuilder();
foreach (var parameter in parameters)
{
//Append a character, generated by our parameter, to our unique string
builder.Append((char) (parameter % 65535));
}
return builder.GetHashCode();
}
This has worked for a long time but has now shown to be quite a major performance bottleneck, even with as few calls as a thousand. The order of the parameters must also affect the resulting seed. In other words; calling SeedByParameters(a, b)
should not give the same seed as SeedByParameters(b, a)
. How could
I achieve a similar functionality with a mathematical algorithm instead of using this string hack?
Firstly, note that there's no such thing as a "unique" hash code. In particular, if you're using a 32 bit hash code and there are more than 2^32 possible combinations of the data for which you're generating the hash code there are guaranteed to be collisions.
Secondly, StringBuilder.GetHashCode()
doesn't do what you think. It does NOT use its contents to generate the hash code, as demonstrated here.
A reasonably performant way to generate a hash code for multiple ints is using the HashCode
struct like so:
public static int SeedByParameters(params int[] array)
{
var hash = new HashCode();
foreach (var n in array)
{
hash.Add(n);
}
return hash.ToHashCode();
}
Note that this is only available for .NET Core 2.1 or later.