C#Decimal.GetHashCode()和Double.GetHashCode()相等 [英] C# Decimal.GetHashCode() and Double.GetHashCode() equal

查看:158
本文介绍了C#Decimal.GetHashCode()和Double.GetHashCode()相等的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么

17m.GetHashCode()== 17d.GetHashCode()

(m = decimal ,d = double)

另外,如预期的

17f.GetHashCode()!= 17d.GetHashCode()

(f = float)

对于net3.5和net4.0,这似乎是正确的。



据了解,这些类型的内部位表示是完全不同的。那么,为什么来自 decimal double 类型的哈希码相同的初始化值呢?在散列计算之前是否有一些转换?



我发现 Double.GetHashCode()的源代码是这样的:

Why is it that
17m.GetHashCode() == 17d.GetHashCode()
(m=decimal, d=double)
Additionally, as expected
17f.GetHashCode() != 17d.GetHashCode()
(f=float)
This appears to be true for both net3.5 and net4.0.

As I understand, the internal bit representations of these types are quite different. So how come that the hash codes of decimal and double types equal for equal initialization values? Is there some conversion taking place before calculation of the hash?

I found that the source code for Double.GetHashCode() is this:

//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()的源代码。我尝试使用方法

I verified that this code returns desired value. But I did not found the source code for Decimal.GetHashCode(). I tried using method

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 type,这也是考虑到小结的内部布局)。所以执行 Decimal.GetHashCode()我目前还不知道。

But this did not match the desired results (it returned the hash corresponding to the int type, which is also expected considering the internal layout of decimal). So the implementation of Decimal.GetHashCode() remains currently unknown to me.

推荐答案

Decimal.GetHashCode()方法在CLR中实现。您可以从SSCLI20源代码中查看可能的实现,clr / vm / comdecimal.cpp:

The Decimal.GetHashCode() method is implemented in the CLR. You can get a peek at the possible implementation from the SSCLI20 source code, clr/vm/comdecimal.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#中的Double.GetHashCode()实现,但用C ++编写,所以获得匹配并不意外。 VarR8FromDec()是一个COM自动化帮助函数将COM DECIMAL转换为双倍。

This is otherwise the exact equivalent of the Double.GetHashCode() implementation in C# but written in C++ so getting a match is not unexpected. VarR8FromDec() is a COM Automation helper function that converts a COM DECIMAL to double.

当然,永远不会依赖这样的匹配。

Of course, never rely on such a match.

更新:它现在看起来一样,CLR是开源的,可以在此github文件。一个皱纹是VarR8FromDec()是Windows或OSX中不可用的Windows功能,它是在PAL中重新实施

UPDATE: it still looks the same now that the CLR is open-sourced, visible in this github file. One wrinkle is that VarR8FromDec() is a Windows function that isn't available in Linux or OSX, it was re-implemented in the PAL.

这篇关于C#Decimal.GetHashCode()和Double.GetHashCode()相等的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆