你怎么实现GetHashCode为结构有两个串,当两个字符串是可以互换的
题
我有一个结构中的C#:
public struct UserInfo
{
public string str1
{
get;
set;
}
public string str2
{
get;
set;
}
}
唯一的规则是 UserInfo(str1="AA", str2="BB").Equals(UserInfo(str1="BB", str2="AA"))
如何复盖GetHashCode功能,用于这种结构?
解决方案
MSDN:
散列函数必须具有以下特性:
- 如果两个对象进行比较平等,
GetHashCode
方法对于每个物体必须返回相同的价值。然而,如果两个物体比较不平等,GetHashCode
方法这两个目的没有返回不同的价值观。- 的
GetHashCode
方法的对象必须始终如一地返回的同一散列代码,如没有修改的对象国家确定返回值的目的Equals
法。注意,这是真实的,仅为当前执行的一个应用程序,不同的散列代码可以返回的,如果应用程序再次运行。- 针对最佳效能,散列函数必须产生一个随机分布于所有的输入。
考虑到正确方法是:
return str1.GetHashCode() ^ str2.GetHashCode()
^
可以取代的其他运作可交换的
其他提示
看看 Jon双向飞碟的答案 -二进制操作的喜欢 ^
不好,他们往往会产生碰撞哈!
public override int GetHashCode()
{
unchecked
{
return (str1 ?? String.Empty).GetHashCode() +
(str2 ?? String.Empty).GetHashCode();
}
}
使用"+"操作者可能比使用'^',因为虽然明确要('AA','BB')和('BB','AA')明确是相同的,你可能不想('AA','AA')和('BB','BB')是相同的(或所有同等对就此而言)。
该'尽可能快地'的规则不是完全遵守这个方案,因为在这种情况下的空值此执行'GetHashCode()'上空串而不是立即恢复一个已知的不变,但即使没有明确地测量我愿意猜测的差不会有足够大的担心,除非你期望很多空。
作为一般规则,一个简单的方法来生成哈希码一类是异或所有的数据字段可以参与生成的散列代码(正在仔细检查null指出其他人)。这也符合(人造的?) 要求hashcodes为UserInfo("AA","BB")和UserInfo("BB","AA")是相同的。
如果你可以进行假设有关使用类,你或许可以提高你的散列函数。例如,如果这是常见的str1and str2是相同的,异或可能不是一个好的选择。但是,如果str1and str2代表说,第一个和最后一个名称、异或可能是一个好的选择。
虽然这显然不意味着是一个现实世界的例子,可能值得指出的是:-这可能是一个贫穷的例子使用的一个结构:一个结构应当通常有价值的语义,这似乎并不是这里的情况。-使用特性与仪生成列码也是自找麻烦。
一个简单的 一般 方式是可以做到这一点:
return string.Format("{0}/{1}", str1, str2).GetHashCode();
除非你有严格的业绩要求,这是最简单我可以想和我经常使用这种方法的时候我需要一个复合的关键。它处理的 null
情况下就好,不会造成(m)任何哈希冲突(一般).如果你期望的'/'在你的串,只是选择另一种隔离,你不要期望。
public override int GetHashCode()
{
unchecked
{
return(str1 != null ? str1.GetHashCode() : 0) ^ (str2 != null ? str2.GetHashCode() : 0);
}
}
沿线ReSharper建议:
public int GetHashCode()
{
unchecked
{
int hashCode;
// String properties
hashCode = (hashCode * 397) ^ (str1!= null ? str1.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (str2!= null ? str1.GetHashCode() : 0);
// int properties
hashCode = (hashCode * 397) ^ intProperty;
return hashCode;
}
}
397是一个主要的足够的大小,导致结果的变量溢流和混合的位的散列有点,提供一个更好的分布哈码。否则没有什么特别在397区别于其他的素数相同的数量级。
是啊,Gary Shutler指出:
return str1.GetHashCode() + str2.GetHashCode();
可能会溢出。你可以试试铸长作为阿尔乔姆建议,或者你可以环绕的声明在未经检查的关键词:
return unchecked(str1.GetHashCode() + str2.GetHashCode());
尝试一下这个:
(((long)str1.GetHashCode()) + ((long)str2.GetHashCode())).GetHashCode()
许多可能性。E.g。
return str1.GetHashCode() ^ str1.GetHashCode()
也许喜欢的东西str1.GetHashCode()+str2.GetHashCode()?或者(str1.GetHashCode()+str2.GetHashCode())/2?这种方式,它将是相同的,无论是否str1and str2交换。...
它们进行排序,然后将他们:
return ((str1.CompareTo(str2) < 1) ? str1 + str2 : str2 + str1) .GetHashCode();
GetHashCode的结果应该是:
- 尽可能快。
- 作为独一无二的,因为可能。
轴承,这些记住,我会去的东西,像这样:
if (str1 == null)
if (str2 == null)
return 0;
else
return str2.GetHashCode();
else
if (str2 == null)
return str1.GetHashCode();
else
return ((ulong)str1.GetHashCode() | ((ulong)str2.GetHashCode() << 32)).GetHashCode();
编辑: 忘了空。代码的固定。
太复杂,而忘记空,等等。这是用于存入桶,所以你能得到的东西一样
if (null != str1) {
return str1.GetHashCode();
}
if (null != str2) {
return str2.GetHashCode();
}
//Not sure what you would put here, some constant value will do
return 0;
这是有偏见的假设str1是不可能的共同在一个不同寻常的大比例的实例。