Instead of concatenating strings (which creates new strings) you could use XOR or even better simple maths (credits to J.SkeetJ.Skeet):
public int keygen(string a, string b, string c) { unchecked // Overflow is fine, just wrap { int hash = 17; hash = hash * 23 + a == null ? 0 : a.GetHashCode(); hash = hash * 23 + b == null ? 0 : b.GetHashCode(); hash = hash * 23 + c == null ? 0 : c.GetHashCode(); return hash; } } In general it's not necessary to produce unique hashs. But you should minimize collisions.
Another(not as efficient) way is to use an anonymous type which has a builtin support for GetHashCode:
public int keygen(string a, string b, string c) { return new { a, b, c }.GetHashCode(); } Note that the name, type and order matters for the calculation of the hashcode of an anonymous type.