前言

如标题所述,在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. 优先队列的基本实现【数据结构与算法—TypeScript 实现】

    笔记整理自 coderwhy 『TypeScript 高阶数据结构与算法』课程 特性 效率比普通队列高 每个出队元素拥有最高优先级 可以用 数组.链表 等数据结构实现,但是 堆结构 是最常用的实现方式 ...

  2. c# 深克隆与浅克隆

    前言 我们都知道memberwiseclone 会将浅克隆. 什么是浅克隆?如何深克隆呢? 正文 public class good{ private good(){ oneclass=new cla ...

  3. Pytorch-tensor的分割,属性统计

    1.矩阵的分割 方法:split(分割长度,所分割的维度),split([分割所占的百分比],所分割的维度) a=torch.rand(32,8) aa,bb=a.split(16,dim=0) pr ...

  4. webpack中常见的Plugin?解决了什么问题?

    一.是什么 Plugin(Plug-in)是一种计算机应用程序,它和主应用程序互相交互,以提供特定的功能 是一种遵循一定规范的应用程序接口编写出来的程序,只能运行在程序规定的系统下,因为其需要调用原纯 ...

  5. next.js app目录 i18n国际化简单实现

    最近在用next写一个多语言的项目,找了好久没找到简单实现的教程,实践起来感觉都比较复杂,最后终于是在官方文档找到了,结合网上找到的代码demo,终于实现了,在这里简单总结一下. 此教程适用于比较简单 ...

  6. 剑指offer56(Java)-数组中出现的次数Ⅰ(中等)

    题目: 一个整型数组 nums 里除两个数字之外,其他数字都出现了两次.请写程序找出这两个只出现一次的数字.要求时间复杂度是O(n),空间复杂度是O(1). 示例 1: 输入:nums = [4,1, ...

  7. 力扣125(java)-验证回文串(简单)

     题目: 给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写. 说明:本题中,我们将空字符串定义为有效的回文串. 示例 1: 输入: "A man, a plan ...

  8. OpenYurt v1.1.0: 新增 DaemonSet 的 OTA 和 Auto 升级策略

    简介: 在 OpenYurt v1.1.0 版本中,我们提供了 Auto 和 OTA 的升级策略.Auto 的升级策略重点解决由于节点 NotReady 而导致 DaemonSet升级阻塞的问题,OT ...

  9. Java应用结构规范

    ​简介:在Java程序开发中,命名和应用分层无疑是广大后端同胞的两大"痛点",本文提供一种基于领域模型的轻量级应用分层结构设计,供大家参考.下面按分层结构.分层明细.调用关系.各层 ...

  10. dotnet 警惕判断文件是否存在因为检查网络资源造成超长等待

    在使用 System.IO.File.Exists 方法时,绝大部分的情况下都是一个非常快捷且没有成本的,但是如果判断的文件是否存在,是从非自己完全控制的逻辑下进入的,那就需要警惕是否判断的文件路径属 ...