如何获取字符串的恒定HashCode(Uint32/Int32)并避开指定范围
.NET Core 字符串持久化哈希码解决方案
一、官方GetHashCode()为啥不能用来持久化
.NET Core里字符串的GetHashCode()每次运行程序都会生成随机值,这是官方为了防止哈希碰撞攻击做的安全设计,肯定不能用来做持久化存储的哈希码。
二、更优的稳定哈希方案
1. 用StringComparer的哈希方法
直接调用StringComparer.Ordinal.GetHashCode("你的字符串"),这个方法的哈希值是稳定的——只要字符串不变,不管运行多少次程序,哈希值都一致。它返回int类型,你可以直接转成uint使用。
2. 自定义轻量哈希算法(直接返回uint)
如果想直接拿到uint类型的哈希值,可以自己实现FNV-1a这种轻量哈希,代码示例:
public static uint GetStableHashCode(string str) { uint hash = 14695981039346656037; // FNV-1a 初始常量 foreach (char c in str) { hash ^= (uint)c; hash *= 1099511628211; // FNV-1a 乘法因子 } return hash; }
这个方法返回的哈希值覆盖整个uint取值区间(0到4294967295),完全满足你要的0-2000之外的范围需求。
3. 用HashCode结构体(.NET Core 2.1及以上)
.NET Core 2.1之后提供了HashCode结构体,你可以手动构建稳定哈希:
public static uint GetStableHashCode(string str) { var hashCode = new HashCode(); foreach (char c in str) { hashCode.Add(c); } return (uint)hashCode.ToHashCode(); }
注意不要添加任何随机相关参数,保证哈希的稳定性。
三、怎么获取0-2000之外的uint类型哈希码
- 上面的自定义FNV方法直接返回uint,范围自然超出0-2000;
- 用
StringComparer.Ordinal.GetHashCode()得到int后转成uint也可行:
string input = "test"; int intHash = StringComparer.Ordinal.GetHashCode(input); uint uintHash = (uint)intHash;
这样得到的uintHash会覆盖0到4294967295的所有数值,完全符合你的范围要求。
内容的提问来源于stack exchange,提问作者Eric Ouellet
相关产品推荐
相关产品推荐

