9


17m.GetHashCode() == 17d.GetHashCode()
(m=decimal, d=double)
さらに、予想どおり
17f.GetHashCode() != 17d.GetHashCode()
(f=float) これは、 net3.5
と net4.0 の両方に当てはまるようです。

私が理解しているように、これらの型の内部ビット表現はまったく異なります。では、 decimal型とdouble型のハッシュ コードが等しく、初期化値が等しいのはなぜでしょうか? ハッシュの計算前に何らかの変換が行われていますか? のソースコードは次のとおり

であることがわかりました。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]);  
} 

しかし、これは望ましい結果と一致しませんでした (型に対応するハッシュを返しました。これは、 decimal の内部レイアウトをint考慮すると予想されます)。したがって、の実装は現在のところ不明です。Decimal.GetHashCode()

4

1 に答える 1

7

Decimal.GetHashCode() メソッドは CLR に実装されています。SSCLI20 のソース コード 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 DECIMAL を double に変換する COM オートメーション ヘルパー関数です。

もちろん、そのような一致に頼ることはありません。


更新: CLR がオープンソース化され、この github ファイルに表示されるようになった今でも同じように見えます。問題の 1 つは、VarR8FromDec() が Linux または OSX では使用できない Windows 関数であり、PAL で再実装されたことです。

于 2012-09-02T15:12:27.290 に答える