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

ハッシュコードの違いは、スケールファクターの違いによって引き起こされる2つの数値の内部表現の違いによるものだと思います。

末尾のゼロを削除することで問題を回避できますが、x == yの場合、GetHashCodeはxとyに同じ値を返す必要があると常に想定していました。この仮定は間違っていますか、それともDecimal.GetHashCodeの問題ですか?

編集:私が使用しているバージョンを明確にするために、Visual Studio 2008 SP1、.NET3.5を使用しています。

4

2 に答える 2

13

これは、Decimal.GetHashCode .NETFrameworkバージョン3.5以下の場合の問題です。2つの値が等しいと見なされる場合、ガイドラインに従って、同じハッシュコードを返す必要があります。この場合、decimal明らかにそうではありません。2つの等しいオブジェクトが同じハッシュコードを持つことを常に期待する必要があります。

MSDNによる

2つのオブジェクトが等しいと比較される場合、各オブジェクトのGetHashCodeメソッドは同じ値を返す必要があります。

複製

さまざまなバージョンの.NETFrameworkに対して正確なコードを試しましたが、結果は次のとおりです。

╔══════════════════╤══════════════════╗
║Framework version │ Hashcode equal ? ║
╟──────────────────┼──────────────────╢
║      2.0         │  No.             ║
║      3.0         │  No.             ║
║      3.5         │  No.             ║
║      4.0         │  Yes.            ║
║      4.5         │  Yes.            ║
╚══════════════════╧══════════════════╝

つまり、.NETFramework4で修正された.NETFrameworkのバグに遭遇したようです。

上記の結果は、Visual Studio 2012 RCを使用し、プロパティページを使用してフレームワークを切り替えることで達成されました。

Microsoftはここでバグを認めています

于 2012-07-02T16:48:29.773 に答える
9

これは、.NET 4より前の.NETバージョンではかなり悪名高いバグでした。Decimal.GetHashCode()実装は、10進値のビット値に依存していました。10進数は分数の既知の桁数を追跡するため、これらは異なります。値にDecimal.GetBits()を使用することで確認できるもの。これがバグであるかどうかは実際には議論の余地があります。小数、着用する眼鏡の種類に応じて異なる値になります。

それにもかかわらず、Microsoftはこれが直感的でない動作であることに同意し、.NET 4で修正しました。関連するフィードバックの記事は、こちらです。

于 2012-07-02T17:19:11.157 に答える