17

可能重复:
C# 为什么相等的小数会产生不相等的哈希值?

我在我的 .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 的版本。

4

2 回答 2

13

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

根据 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,使用属性页切换框架达到的。

微软在这里承认了这个错误

于 2012-07-02T16:48:29.773 回答
9

这是 .NET 4 之前的 .NET 版本中相当臭名昭著的错误。 Decimal.GetHashCode() 实现依赖于十进制值中的位值。它们是不同的,因为十进制跟踪分数中已知数字的数量。您可以通过对值使用 Decimal.GetBits() 来查看。这是否是一个错误实际上是有争议的,小数确实有不同的值,这取决于你戴什么样的眼镜。

尽管如此,Microsoft 同意这是不直观的行为,并在 .NET 4 中对其进行了修复,相关的反馈文章在此处

于 2012-07-02T17:19:11.157 回答