前言

如标题所述,在ASP.NET Core应用程序中,使用string.GetHashCode()方法去获取字符串的哈希值,但每次重启这个ASP.NET Core应用程序之后,同样的字符串的哈希值(hash)但不相同了。这是什么意思呢?

具体的应用场景是这样的: 项目中有一张表的某个字段保存了类似URL这样的字符串,这张表的数据量比较大,而且这个字段会被经常用作检索。所以,为了提高查询效率,在存储的时候同时存储了这个URL字段的哈希值(hash)。

原来ASP.NET MVC 5项目的.NET Framework版本中,随便应用程序怎么重启,使用string.GetHashCode()方法获取到的哈希值永远都是一致的(也需要保持一致)。

但在ASP.NET Core 应用程序中,使用string.GetHashCode()方法,就出现了上述的问题,导致程序在相应的功能部分也出现Bug。最终经过多次测试和查阅资料,定位到了问题的原因。

问题重现

这里我重现一下问题的场景,以下是.NET Framework 4.6.1版本的string.GetHashCode()方法在不断重启程序之后获取到的哈希值(hash),每次获取到的都是相同的值:

using System;

namespace ConsoleApp2
{
class Program
{
static void Main()
{
var str = "Hello world";
Console.WriteLine(str.GetHashCode());
Console.ReadKey();
}
}
}

输出:-1660742776

但是,如果在.NET Core应用程序中执行以上相同的代码,每次重启程序后获取到的哈希值是不相同的。

比如我重启测试了三次.NET Core应用程序,分别得到了三个不同的哈希值:313140527-11693814872141605647

在定位到问题之后,我们得找出生成不同哈希值的原因。经过一番努力查找之后,其实微软官方文档给出过使用GetHashCode()方法的建议(文档地址)。其中也明确提示了,不应该将使用.NET内置的GetHashCode()方法获取到的值作为持久化的值。

Hash codes are used to insert and retrieve keyed objects from hash tables efficiently. However, hash codes don’t uniquely identify strings. Identical strings have equal hash codes, but the common language runtime can also assign the same hash code to different strings. In addition, hash codes can vary by version of .NET, by platform within a single version, and by application domain. Because of this, you should not serialize or persist hash code values, nor should you use them as keys in a hash table or dictionary.

如何获取一个恒定的哈希值(hash)

那要确保.NET Framework和.NET Core应用程序获取到的哈希值都是相同的,我们需要自定义实现哈希值的算法,以下列出一个可行的算法:

public static class HashHelper
{
public static int GetDeterministicHashCode(this string str)
{
unchecked
{
int hash1 = (5381 << 16) + 5381;
int hash2 = hash1; for (int i = 0; i < str.Length; i += 2)
{
hash1 = ((hash1 << 5) + hash1) ^ str[i];
if (i == str.Length - 1)
break;
hash2 = ((hash2 << 5) + hash2) ^ str[i + 1];
} return hash1 + (hash2 * 1566083941);
}
}
}

完整调用示例(.NET Core):

using System;

namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
var str = "Hello world";
Console.WriteLine(str.GetDeterministicHashCode());
Console.WriteLine(str.GetDeterministicHashCode());
Console.WriteLine(str.GetDeterministicHashCode());
Console.WriteLine("****************************");
Console.WriteLine(str.GetHashCode());
Console.WriteLine(str.GetHashCode());
Console.WriteLine(str.GetHashCode());
Console.ReadKey();
}
} public static class HashHelper
{
public static int GetDeterministicHashCode(this string str)
{
unchecked
{
int hash1 = (5381 << 16) + 5381;
int hash2 = hash1; for (int i = 0; i < str.Length; i += 2)
{
hash1 = ((hash1 << 5) + hash1) ^ str[i];
if (i == str.Length - 1)
break;
hash2 = ((hash2 << 5) + hash2) ^ str[i + 1];
} return hash1 + (hash2 * 1566083941);
}
}
}
}
 
 
 

.NET Core应用程序每次启动后使用string.GetHashCode()方法获取到的哈希值(hash)不相同的更多相关文章

  1. springboot 学习之路 9 (项目启动后就执行特定方法)

    目录:[持续更新.....] spring 部分常用注解 spring boot 学习之路1(简单入门) spring boot 学习之路2(注解介绍) spring boot 学习之路3( 集成my ...

  2. 在tomcat启动时解析xml文件,获取特定标签的属性值,并将属性值设置到静态变量里

    这里以解析hibernate.cfg.xml数据库配置信息为例,运用dom4j的解析方式来解析xml文件. 1.在javaWeb工程里新建一个java类,命名为GetXmlValue.java,为xm ...

  3. Mysql启动后停止的解决方法

    安装mysql后,服务无法正常启动,报错如下: 解法方法: 1           以管理员身份运行命令提示符 2           用命令进行mysql安装目录的bin目录: cd C:\Prog ...

  4. 关于微信小程序拒绝授权后,重新授权并获取用户信息

    最近公司做了一些有关微信小程序的项目,涉及到授权获取用户基本信息,但是在拒绝授权之后就不会再出现授权窗口: 看网上也有很多人遇到了同样的问题,所以记录下来我的处理方法,供大家和自己学习和记录: 当调用 ...

  5. Android应用程序进程启动过程(后篇)

    前言 在前篇中我们讲到了Android应用程序进程启动过程,这一篇我们来讲遗留的知识点:在应用程序进程创建过程中会启动Binder线程池以及在应用程序进程启动后会创建消息循环. 1.Binder线程池 ...

  6. ASP.NET Core应用程序容器化、持续集成与Kubernetes集群部署(一)(转载)

    本文结构 ASP.NET Core应用程序的构建 ASP.NET Core应用程序容器化所需注意的问题 应用程序的配置信息 端口侦听 ASP.NET Core的容器版本 docker镜像构建上下文(B ...

  7. 让微信小程序每次请求的时候不改变session_id的方法

    让微信小程序每次请求的时候不改变session_id的方法 每次微信小程序请求的时候都会改变session id, 还好他的请求方法内可以设置header头 所以只需要在启动程序后第一次请求服务器获得 ...

  8. 【Spring容器】项目启动后初始化数据的两种实践方案

    早期业务紧急,没有过多的在意项目的运行效率,现在回过头看走查代码,发现后端项目(Spring MVC+MyBatis)在启动过程中多次解析mybatis的xml配置文件及初始化数据,对开发阶段开发人员 ...

  9. AspNet Core Web 应用程序的启动 当项目中 没有Startup.cs 类如何设置启动 配置等等

    感叹: Core 16年6月1号 在中国宣布上线 到现在已经快经历两年时间了,目前版本已经到了2.0 就目前的前景来看,个人感觉 到2020年才可能有所起色,等到Core更成熟 个人看法:在.net这 ...

  10. 病症:arm启动后应用程序界面显示…

    病症:病症:arm启动后应用程序界面显示不正常(左面有部分未能正常显示)也就是左面少一块区域,右面多一部, 原因:lcd显示驱动中场扫描的问题 平台:s3c2416.linux2.6.800*480l ...

随机推荐

  1. 开发指导—利用CSS动画实现HarmonyOS动效(一)

     注:本文内容分享转载自HarmonyOS Developer官网文档 一. CSS语法参考 CSS是描述HML页面结构的样式语言.所有组件均存在系统默认样式,也可在页面CSS样式文件中对组件.页面自 ...

  2. Bill的挑战

    看数据范围就知道应该要状压,也不难看出应该压缩位数的状态.所以设f[i][j]为前i位,相互匹配的字符串的状态. 那么,就会有 f[i+1][j&a[i][ch]]=(f[i+1][j& ...

  3. ImportError: Cannot load backend 'TkAgg' which requires the 'tk' interactive framework, as 'headless' is currently running

    MMdetection多卡训练常遇到的两个错误,百度无果,没解决,去github里mmdetection的issue模块搜索了一下找到正解. 这里记录一下,方便后者. 1️⃣ ImportError: ...

  4. Flagger on ASM——基于Mixerless Telemetry实现渐进式灰度发布系列 2 应用级扩缩容

    简介: 应用级扩缩容是相对于运维级而言的.像监控CPU/内存的利用率就属于应用无关的纯运维指标,针对这种指标进行扩缩容的HPA配置就是运维级扩缩容.而像请求数量.请求延迟.P99分布等指标就属于应用相 ...

  5. 阿里云力夺FewCLUE榜首!知识融入预训练+小样本学习的实战解析

    简介: 7月8日,中文语言理解权威评测基准CLUE公开了中文小样本学习评测榜单最新结果,阿里云计算平台PAI团队携手达摩院智能对话与服务技术团队,在大模型和无参数限制模型双赛道总成绩第一名,决赛答辩总 ...

  6. Puppeteer 入门与进阶: 快速上手

    Puppeteer API: https://puppeteer.bootcss.com/api 1. 安装: $ yarn add puppeterr 2. 网页截图实例: // main.jsco ...

  7. [Go] panic: assignment to entry in nil map

    以上错误出现在给 map 变量赋值的时候. 例如: type AbMap map[string]string var abMap AbMap abMap['a'] = 'b' 使用 map 变量需要使 ...

  8. MSBuild 输出日志可视化工具 MSBuild Structured Log Viewer 简介

    感谢 Vatsan Madhavan 小伙伴推荐的 MSBuild 输出日志可视化工具,这个工具可以使用漂亮的 WPF 界面预览 MSBuild 复杂的输出内容 这是一个完全开源的工具,请看 Kiri ...

  9. 2019-8-31-C#-简单读取文件

    title author date CreateTime categories C# 简单读取文件 lindexi 2019-08-31 16:55:58 +0800 2018-07-19 16:48 ...

  10. 一步步教你在 Windows 上构建 dotnet 系应用的 UOS 软件安装包

    本文将详细指导大家如何逐步为 dotnet 系列应用创建满足 UOS 统信系统软件安装包的要求.在这里,我们所说的 dotnet 系列应用是指那些能够在 Linux 平台上构建 UI 框架的应用,包括 ...