Decimal.GetHashCode取决于尾随零

MrK*_*ins 16 .net c#

可能重复:
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());
Run Code Online (Sandbox Code Playgroud)

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

1085009409
1085009408
True
False
Run Code Online (Sandbox Code Playgroud)

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

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

编辑:要清楚我正在使用Visual Studio 2008 SP1,.NET 3.5的版本.

dri*_*iis 12

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.            ?
???????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)

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

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

微软承认这里的错误.


Han*_*ant 9

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

然而,微软同意这是不直观的行为,并在.NET 4中修复它,相关的反馈文章就在这里.