Decimal.GetHashCode取决于尾随零

时间:2012-07-02 16:44:18

标签: c# .net

  

可能重复:
  C# Why can equal decimals produce unequal hash values?

我在.NET 3.5应用程序中遇到了一个问题(x86或x64,我已经尝试了两种),其中具有不同数量的尾随零的小数具有不同的哈希码。例如:

decimal x = 3575.000000000000000000M;
decimal y = 3575.0000000000000000000M;

Console.WriteLine(x.GetHashCode());
Console.WriteLine(y.GetHashCode());
Console.WriteLine(x == y);
Console.WriteLine(x.GetHashCode() == y.GetHashCode());

在我的机器上输出以下内容:

1085009409
1085009408
True
False

我认为哈希码的差异是由不同比例因子引起的两个数字的不同内部表示。

虽然我可以通过删除尾随零来解决这个问题,但我总是假设GetHashCode应该为x和y返回相同的值,如果x == y。这个假设是错误的,还是Decimal.GetHashCode的问题?

编辑:要清楚我使用的是Visual Studio 2008 SP1,.NET 3.5。

2 个答案:

答案 0 :(得分:12)

对于.NET Framework 3.5及更低版本,这是Decimal.GetHashCode 的问题。当两个值被认为相等时,它们必须按照指南返回相同的哈希码;在这种情况下,decimal显然没有。您应始终期望两个相等的对象具有相同的哈希码。

Per MSDN

  

如果两个对象比较相等,则每个对象的GetHashCode方法   对象必须返回相同的值。

再生

我已针对不同版本的.NET Framework尝试了您的确切代码,结果如下:

╔══════════════════╤══════════════════╗
║Framework version │ Hashcode equal ? ║
╟──────────────────┼──────────────────╢
║      2.0         │  No.             ║
║      3.0         │  No.             ║
║      3.5         │  No.             ║
║      4.0         │  Yes.            ║
║      4.5         │  Yes.            ║
╚══════════════════╧══════════════════╝

换句话说,您似乎偶然发现了.NET框架中的一个错误,该错误已通过.NET Framework 4修复。

使用Visual Studio 2012 RC,使用属性页切换框架,达到了上述结果。

Microsoft acknowledges the bug here

答案 1 :(得分:9)

在.NET 4之前的.NET版本中,这是一个相当infamous bug .Decimal.GetHashCode()实现依赖于十进制值中的位值。它们是不同的,因为小数跟踪分数中已知数字的数量。通过在值上使用Decimal.GetBits()可以看到的东西。这是否是一个错误实际上是有争议的,小数具有不同的值,这取决于你穿什么样的眼镜。

然而,微软同意这是不直观的行为,并在.NET 4中修正了相关的反馈文章is here