.net 4.0 为什么这些哈希码是相等的?
此测试失败:.net 4.0 为什么这些哈希码是相等的?,.net-4.0,gethashcode,.net 4.0,Gethashcode,此测试失败: var hashCode = new { CustomerId = 3354, ServiceId = 3, CmsThematicId = (int?)605, StartDate = (DateTime?)new DateTime(2013, 1, 5), EndDate = (DateTime?)new DateTime(2013, 1, 6) }.GetHashCode(); var hashCode2 = new { Cu
var hashCode = new
{
CustomerId = 3354,
ServiceId = 3,
CmsThematicId = (int?)605,
StartDate = (DateTime?)new DateTime(2013, 1, 5),
EndDate = (DateTime?)new DateTime(2013, 1, 6)
}.GetHashCode();
var hashCode2 = new
{
CustomerId = 1210,
ServiceId = 3,
CmsThematicId = (int?)591,
StartDate = (DateTime?)new DateTime(2013, 3, 31),
EndDate = (DateTime?)new DateTime(2013, 4, 1)
}.GetHashCode();
Assert.AreNotEqual(hashCode, hashCode2);
你能告诉我为什么吗?你发现这个巧合有点令人惊讶 匿名类有一个生成的
GetHashCode()
方法,该方法通过组合所有属性的哈希代码来生成哈希代码
计算基本上是这样的:
public override int GetHashCode()
{
return -1521134295 *
( -1521134295 *
( -1521134295 *
( -1521134295 *
( -1521134295 *
1170354300 +
CustomerId.GetHashCode()) +
ServiceId.GetHashCode()) +
CmsThematicId.GetHashCode()) +
StartDate.GetHashCode()) +
EndDate.GetHashCode();
}
如果更改任何字段的任何值,哈希代码也会更改。您发现两组不同的值恰好得到相同的哈希代码,这是一个巧合
请注意,哈希代码不一定是唯一的。不可能说哈希代码总是唯一的,因为可以有比哈希代码更多的对象(尽管这是很多对象)。好的散列码提供值的随机分布
注:以上内容来自.NET4。不同版本的.NET可能不同,Mono也可能不同
如果要实际比较两个对象是否相等,请使用.Equals()
。对于匿名对象,它会比较每个字段。更好的选择是使用NUnit约束来比较每个字段并报告不同的字段。我在这里发布了一个约束:
您在处理大量数据时遇到过这种情况吗 欢迎来到哈希代码的奇妙世界。哈希代码不是“唯一标识符”。它不能是唯一标识符。该匿名类型的不同实例的数量基本上是无限的,但只有2^32个可能的哈希代码。所以可以保证,如果你创建了足够多的对象,你会看到一些重复的对象。事实上,如果随机生成70000个对象,那么其中两个对象具有相同哈希代码的可能性大于50% 有关更多信息,请参阅和链接的Wikipedia文章 至于为什么有些人看不到副本,而有些人看到了,很可能是他们在不同版本的.NET上运行了这个程序。生成哈希代码的算法不能保证在不同版本或平台上保持不变: 对象的GetHashCode方法必须始终返回相同的值 哈希代码,只要不修改 确定对象的Equals方法的返回值注意 这仅适用于应用程序的当前执行,并且 如果应用程序运行,则可以返回不同的哈希代码 再次
你的测试无效 因为不能保证哈希代码是唯一的(请参阅其他答案以获得更好的解释),所以不应该测试哈希代码的唯一性 编写自己的
GetHashCode()
方法时,最好测试随机输入的均匀分布,而不是唯一性。只要确保你使用了足够的随机输入来获得一个好的测试
GetHashCode上的MSDN规范明确指出:为了获得最佳性能,哈希函数必须生成一个随机变量 所有输入的分配 当然,这都是相对的。用于将100个对象放入字典的
GetHashCode()
方法不需要像将10000000个对象放入字典的GetHashCode()
方法那样随机。吉姆建议我(在聊天室中)存储参数,因此当我显示参数时,选择未使用的参数,然后,当有人注册时,我将其标记为已使用。但生成所有参数是一个很大的PITA
所以我的解决方案是构建一个像这样的int64哈希代码
const long i = -1521134295;
return -i * (-i * (-i * (-i * -117147284 + customerId.GetHashCode()) + serviceId.GetHashCode()) + cmsThematicId.GetHashCode()) + startDate.GetHashCode();
我删除了结束日期,因为它的值取决于serviceId和startDate,所以我不应该首先将其添加到hashcode中。
我从生成的类的反编译中复制/粘贴它。如果我用30万种不同的组合做测试,我就不会有结肠绞痛。。他说得对。此代码确实生成相同的哈希代码。不要这么快就投票否决别人。@dasblinkenlight,运行代码。散列码是一样的。@SamuelNeff我刚刚做了-我上面的评论是到ideone的链接。我得到了429571660和-626441557..net4在标签中,如果我使用它,我会添加mono。随机分布是什么意思?随机分布不是一个准确的陈述。它应该说明的是随机输入的均匀分布。我会更新。我需要这些是唯一的,因为我想确保数据库中没有具有相同值组合的记录,您认为我应该如何做?我需要有效率,因为我要处理大量的数据。@remibourgarel:如果不了解更多关于数据的信息以及您如何使用这些数据,或者您希望这个独特的密钥做什么,就很难给出建议。一般来说,任何哈希方案都不能保证唯一性;总是有碰撞的危险。除非你说的是完美散列,这是一个非常特殊的情况。发布另一个问题,详细说明您正在尝试做什么,我们可能会提供解决方案。