注意 .NET string.GetHashCode() 用法

需求案例:需要把字符串存入数据库,并且要求数据库中不能有重复的字符串,由此就引出了将字符串hash成特定的hash值,依靠查询hash值是否重复来判断字符串是否重复。这样做的好处在于查询重复字符串的代价太大,因为字符串可能会非常长,进行逐个比较非常消耗数据库的性能,如果将字符串hash之后,依靠hash值来查重就显得轻便很多了,因为hash值通常都比字符串本身短很多。由于使用的是C#,自然而然就用了string的GetHashCode函数,MSDN上说该函数得到的返回值可以唯一区别一个string,意思就是相同的字符串肯定会得到相同的hash值,不同的字符串的hash值肯定不一样。当时还在疑惑,这个函数的返回值是int型,算起来也就几十亿,但是字符串的组合却是无穷的啊,微软是怎么实现唯一性的呢?

测试结果:调试代码发现用hash值查询一个数据库中已经存在的string,居然说没有重复!这就相当让人费解了,string已经存在了,那么其hash值也肯定已经存在在数据库中,怎么会说没有重复呢?仔细debug代码,惊讶的发现原来string的hash值居然变了,变成了一个和数据库中完全不同的值。

那么为什么同一个string,两次运行GetHashCode得到的返回值却不一样呢?

原来GetHashCode只是保证在同一个进程的内存空间中,string的返回值可以唯一区别一个string。在同一个进程的内存空间中,每个string的hash值都被微软保证不会重复(除非两个string的内容一样),虽然字符串的组合是无限的,但是对于一个进程的内存空间,顶多就几个G的,几个G的内存所能容纳的string的组合就变成了“有限的”了,int型的几十亿足够来保证这些“有限的”string组合有不同的hash值。
但是微软不保证同一个string在调用GetHashCode之后得到的返回值是相同的!因为int就几十亿,如果用来保证每次调用得到的返回值相同,那么势必出现hash值的碰撞。
这也是为什么MD5,SHA2等hash算法得到的返回值都是128位或者256位的原因,因为只有足够长,才能保证少发生碰撞或者发生碰撞之后可以二次hash。

PS:看看微软对这个函数的备注
http://msdn.microsoft.com/zh-cn/library/system.string.gethashcode.aspx
备注
GetHashCode 的行为取决于它的实现,此实现可能会从一个公共语言运行时版本更改为另一个版本。 原因可能是为了提高 GetHashCode 的性能。
说明说明
如果两个字符串对象相等,则 GetHashCode 方法返回相同的值。 但是,每个唯一的字符串值并没有唯一的哈希代码值。 不同的字符串可以返回相同的哈希代码。
有关哈希代码的更多信息,请参见 Object.GetHashCode。

时间: 2024-08-14 16:45:54

注意 .NET string.GetHashCode() 用法的相关文章

C#中string.format用法详解 [转载]

这篇文章主要介绍了C#中string.format用法,以实例形式较为详细的讲述了string.format格式化的各种用法,非常具有实用价值,需要的朋友可以参考下 本文实例总结了C#中string.format用法.分享给大家供大家参考.具体分析如下: String.Format 方法的几种定义: String.Format (String, Object) 将指定的 String 中的格式项替换为指定的 Object 实例的值的文本等效项.String.Format (String, Obj

String.Format用法

1.作为参数   名称 说明   Format(String, Object) 将指定的 String 中的格式项替换为指定的 Object 实例的值的文本等效项.   Format(String, array<>[]()[]) 将指定 String 中的格式项替换为指定数组中相应 Object 实例的值的文本等效项.   Format(IFormatProvider, String, array<>[]()[]) 将指定 String 中的格式项替换为指定数组中相应 Object

C#中string.Format 用法详解

这篇文章主要介绍了C#中string.format用法,以实例形式较为详细的讲述了string.format格式化的各种用法,非常具有实用价值,需要的朋友可以参考下 本文实例总结了C#中string.format用法.分享给大家供大家参考.具体分析如下: String.Format 方法的几种定义: String.Format (String, Object) 将指定的 String 中的格式项替换为指定的 Object 实例的值的文本等效项.String.Format (String, Obj

C#里sqlDataAdapter.fill(DataSet,String)的用法

第二个参数 String是指定DataSet 里表的名字,例如 sqlDataAdapter.fill(DataSet,"学生表") 指定后,以后就可以这样调用这张表 DataSet.Tables["学生表"] 第二个参数可以不要的,如果不要第二个参数 String 那你调用这张表只能通过索引号,例如 DataSet.Tables[0] 如果填充的表比较多的话,用这个参数比较容易管理和调用. C#里sqlDataAdapter.fill(DataSet,String

String的用法总结-swift

学习swift的String用法总结 学习了swift的String的用法之后感觉比OC的太直接了,不需要直接的初始化.类型声明也不用区分可变和不可变的类型,基本上就是属于哪里需要就在哪里直接写就可以的状态 override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. print("viewDidLoad"

java成神之——java中string的用法

java中String的用法 String基本用法 String分割 String拼接 String截取 String换行符和format格式化 String反转字符串和去除空白字符 String获取指定位置字符和replace的使用 StringBuffer的使用 字符串转换 基本类型的转换 添加字符编码 Base64的编码和解码 结语 java中String的用法 String基本用法 字符串一旦创建在堆中就不可变 字符串声明 String str = "你好"; String s

C++ STL(一)string的用法

# 1.string的用法- string在<iostream>的头中就有,但是还是得用<string>的头 ##### 构造函数- str(const char* ch) 直接赋值- str(size_t n,char ch) 赋值n个ch字符- str(char* ch,size_t n) 取ch指针的前n位- str(string& str,size_t index,size_t length) 从index开始取length位- str(string& st

map和string的用法

这个是别人写的map用法比较好可以看一下 http://www.cnblogs.com/anywei/archive/2011/10/27/2226830.html 如何向数组中插入内容 http://www.360doc.com/content/12/0417/16/3349869_204420932.shtml string 的主要一点记住 string类型是可以加char型的 这样在文本处理时就方便许多了 代码如下 #include<cstdio> #include<string&

C++string类用法

1.string类的输入操作(string类重载运算符operator>>用于输入,同样重载运算符operator<<用于输出操作) operator是C++的关键字,它和运算符一起使用,表示一个运算符函数,理解时应将operator=整体上视为一个函数名. 这是C++扩展运算符功能的方法.关于operator的更多内容不在这里详细说明 string str1;      cin >> str1;     //当用cin>>进行字符串的输入的时候,遇到空格的