为什么
17m.GetHashCode() == 17d.GetHashCode()
(m=decimal,d=double)
此外,如预期的那样
17f.GetHashCode() != 17d.GetHashCode()
(f=float)
对于net3.5和net4.0来说,这似乎都是正确的。
据我所知,这些类型的内部位表示是非常不同的。那么,为什么十进制和双类型的哈希码对于相同的初始化值相等呢?在计算散列之前是否进行了一些转换?
我发现Double.GetHashCode()的源代码如下:
//The hashcode for a double is the absolute value of the integer representation
//of that double.
//
[System.Security.SecuritySafeCritical] // auto-generated
public unsafe override int GetHashCode() {
double d = m_value;
if (d == 0) {
// Ensure that 0 and -0 have the same hash code
return 0;
}
long value = *(long*)(&d);
return unchecked((int)value) ^ ((int)(value >> 32));
} 我验证了这段代码是否返回所需的值。但是我没有找到Decimal.GetHashCode()的源代码。我试着用方法
public static unsafe int GetHashCode(decimal m_value) {
decimal d = m_value;
if (d == 0) {
// Ensure that 0 and -0 have the same hash code
return 0;
}
int* value = (int*)(&d);
return unchecked(value[0] ^ value[1] ^ value[2] ^ value[3]);
} 但这与所需的结果不匹配(它返回了与int类型对应的散列,这也是考虑到十进制内部布局的情况)。因此,Decimal.GetHashCode()的实现对我来说仍然是未知的。
发布于 2012-09-02 15:12:27
Decimal.GetHashCode()方法是在CLR中实现的。您可以从SSCLI20源代码clr/vm/com.jal.cpp获得可能的实现:
double dbl;
VarR8FromDec(d, &dbl);
if (dbl == 0.0) {
// Ensure 0 and -0 have the same hash code
return 0;
}
return ((int *)&dbl)[0] ^ ((int *)&dbl)[1];否则,这与C#中的C#实现完全相同,但它是用C++编写的,因此获得匹配并不是意料之外的。VarR8FromDec()是一个COM自动化助手函数,它将COM十进制转换为双进制。
当然,永远不要依赖这样的匹配。
更新:既然CLR是开源的,在这个github文件中是可见的,它看起来还是一样的。一个缺点是VarR8FromDec()是一个在Linux或OSX中不可用的在PAL中重新实现函数,它是在PAL中重新实现。
https://stackoverflow.com/questions/12236499
复制相似问题