Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/304.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如果不能保证字符串或整数的getHashCode()是唯一的,为什么要使用它?_C#_Linq_Hashcode_Iequalitycomparer - Fatal编程技术网

C# 如果不能保证字符串或整数的getHashCode()是唯一的,为什么要使用它?

C# 如果不能保证字符串或整数的getHashCode()是唯一的,为什么要使用它?,c#,linq,hashcode,iequalitycomparer,C#,Linq,Hashcode,Iequalitycomparer,正如我在标题中所写 如果在应用程序中使用getHashCode()不安全,为什么要使用它?(用于字符串和整数) 我想用它来交集Linq模型中的方法和方法 或者创建我自己的IEqualityCompare类。 这感觉像是一个机会——如果不是100%安全的话 还是我错过了什么 如中String.GetHashCode方法中所引用 重要的 如果两个字符串对象相等,则GetHashCode方法返回相同的值。但是,对于每个唯一的字符串值,没有唯一的哈希代码值。不同的字符串可以返回相同的哈希代码 哈希代码本

正如我在标题中所写

如果在应用程序中使用getHashCode()不安全,为什么要使用它?(用于字符串和整数) 我想用它来交集Linq模型中的方法和方法 或者创建我自己的IEqualityCompare类。 这感觉像是一个机会——如果不是100%安全的话

还是我错过了什么

如中String.GetHashCode方法中所引用

重要的

如果两个字符串对象相等,则GetHashCode方法返回相同的值。但是,对于每个唯一的字符串值,没有唯一的哈希代码值。不同的字符串可以返回相同的哈希代码

哈希代码本身不能保证是稳定的。对于单个版本的.NET,相同字符串的哈希代码在.NET实现、.NET版本和.NET平台(如32位和64位)之间可能有所不同。在某些情况下,它们甚至可能因应用程序域而异。这意味着同一程序的两次后续运行可能会返回不同的哈希代码

因此,哈希代码决不能在其所在的应用程序域之外使用 创建时,它们决不能用作集合中的键字段,也决不能持久化

最后,在以下情况下,不要使用哈希代码而不是加密哈希函数返回的值 您需要一个加密性强的散列。对于加密哈希,请使用从 System.Security.Cryptography.HashAlgorithm或System.Security.Cryptography.KeyedHashAlgorithm类

有关哈希代码的更多信息,请参阅Object.GetHashCode


我想让你感到困惑的是,你认为,散列代码映射到一个值的地址,但它不是那样的

想象一下,它就像书架,散列代码映射到书架的地址。如果其中两个具有相同的哈希代码,将放在同一个书架上,并且有一个书架的地址,其中有3本书,则字典只检查书架上的3本书,而不是所有的书。因此,哈希代码越独特,字典查找的速度就越快

创建
IEqualityComparer
时,如果可以使
GetHashCode()
返回唯一的值,则使用它的字典或哈希集的执行速度将比有许多重复项时快

检查此示例:

public int GetShashCode(string ojb)
{
     return obj.Length;
}
虽然它比在整个字符串中循环快得多,但它不是很独特(尽管它是有效的)

此示例同样有效,但更糟糕的选择是:

public int GetShashCode(string ojb)
{
     return (int)obj[0];
}
根据您可以猜测的字符串内容,您可以制作更好的哈希代码(例如,您知道它是一个社会保险号码,格式为:“XXX-XX-XXXX”,每个X代表一个数字),这将是一个不错的选择:

public int GetShashCode(string ojb)
{
     return int.Parse(obj.Replace("-",""));
}
如果在应用程序中使用getHashCode()不安全,为什么要使用它

有不同的目的。如果您需要对字符串进行相等性测试,您可能应该使用or
=
运算符,这些运算符保证正常工作

哈希代码不是为每个可能的字符串生成唯一数字的方法,这是不可能的。以下是对以下各项的定义:

哈希函数是可用于将任意大小的数据映射到固定大小值的任何函数

它只是将一组几乎无限的字符串映射到一组(相对而言)非常有限的整数。如果需要将大量字符串均匀地分布到较小的“bucket”,则可能需要使用哈希代码。哈希代码广泛用于基于哈希的集合,例如

GetHashCode
的文档提到了此方法的不同问题:

  • 该方法可以为不同域/计算机/版本的.Net上的相同字符串生成不同的结果。这意味着将散列作为某种唯一标识符存储在外部供以后使用不是一个好主意
  • 其结果在加密方面并不强大,因此如果您需要一个不可破解的密码,就不应该使用它
当然,这看起来很吓人,但是,
GetHashCode
对于内存中的集合来说已经足够好了,比如
HashSet
Dictionary


另外,请看这个问题:

来自
GetHashCode
的哈希不是安全哈希,但是除了
Intersect
之外,
可能不需要安全哈希。我想重点是“两次后续运行”我从未注意到同一AppDomain中的两个string.GetHashCode调用都返回了两个不同的HashCode。我最近尝试使用GetHashCode来评估我的序列化对象图和反序列化对象图是否基于其值GetHashCode相同,它们与我重新启动应用程序时的值不同。只有在我的单元测试中,它们与调用序列化和反序列化的过程相同。
GetHashCode
不是为了安全。唯一的目的是生成一个索引。您引用的文档明确指出,不要使用
GetHashCode
进行安全哈希,而是使用
System.Security.Cryptography
命名空间中的类。您永远不会只使用GetHashCode(),接下来使用Equals()来测试是否相等。关键是散列可以显著减少您必须执行的相等性测试的数量。这是如何产生代码的主要加速的,这在中得到了很好的演示。如果我没记错的话,.net Framework中的底层GetHashCode实现就是要考虑指针值,对于原语值,它在字符串表中的位置(忘记了该表是如何调用的)