6

ByteArray内部でバイト配列を使用する独自の不変クラスを作成しながら、IStructuralEquatableインターフェイスを実装しました。私の実装では、ハッシュコードを計算するタスクを内部配列に委任しました。テスト中に、驚いたことに、2つの異なる配列が同じ構造ハッシュコードを持っていることがわかりました。つまり、から同じ値を返しましたGetHashCode。再現するには:

IStructuralEquatable array11 = new int[] { 1, 1 };
IStructuralEquatable array12 = new int[] { 1, 2 };
IStructuralEquatable array22 = new int[] { 2, 2 };

var comparer = EqualityComparer<int>.Default;
Console.WriteLine(array11.GetHashCode(comparer));     // 32
Console.WriteLine(array12.GetHashCode(comparer));     // 32
Console.WriteLine(array22.GetHashCode(comparer));     // 64

IStructuralEquatableは非常に新しく未知ですが、コレクションと配列の内容を比較するために使用できることをどこかで読みました。私は間違っていますか、それとも私の.Netは間違っていますか?

私が話しているのではないObject.GetHashCodeことに注意してください!

編集:それで、等しくないオブジェクトは等しいハッシュコードを持っているかもしれないので、私は明らかに間違っています。しかしGetHashCode、いくらかランダムに分散された値のセットを返すことは要件ではありませんか?さらにテストを行った結果、最初の要素が同じ2つの配列のハッシュが同じであることがわかりました。私はまだこれは奇妙な行動だと思います。

4

3 に答える 3

15

あなたが説明したことはバグではありません。 GetHashCode()等しくないオブジェクトの一意のハッシュは保証されません。

MSDNから:

2 つのオブジェクトを比較して等しい場合、各オブジェクトの GetHashCode メソッドは同じ値を返す必要があります。ただし、2 つのオブジェクトが等しくない場合、2 つのオブジェクトの GetHashCode メソッドは異なる値を返す必要はありません。

編集

GetHashCode()forの MSFT .NET 実装はArray.IStructuralEquatable、上記の MSDN ドキュメントの原則に従っていますが、作成者が意図したとおりに実装していないようです。

「Array.cs」のコードは次のとおりです。

    int IStructuralEquatable.GetHashCode(IEqualityComparer comparer) { 
        if (comparer == null)
            throw new ArgumentNullException("comparer"); 
        Contract.EndContractBlock();

        int ret = 0;

        for (int i = (this.Length >= 8 ? this.Length - 8 : 0); i < this.Length; i++) {
            ret = CombineHashCodes(ret, comparer.GetHashCode(GetValue(0))); 
        } 

        return ret; 
    }

特に次の行に注意してください。

ret = CombineHashCodes(ret, comparer.GetHashCode(GetValue(0)));

私が間違っていない限り、それ0i. このため、GetHashCode()常に同じ max(0, n-8) 要素を持つ配列に対して同じ値を返します。n は配列の長さです。これは間違って0いません (ドキュメントに違反していません) が、に置き換えた場合ほど良くないことは明らかiです。また、コードが配列から単一の値を使用するだけの場合、ループする理由はありません。

于 2012-07-29T23:59:53.607 に答える
0

GetHashCode等しくないインスタンスに対して一意の値を返しません。ただし、等しいインスタンスは常に同じハッシュ コードを返します。

Object.GetHashCodeメソッドから引用するには:

2 つのオブジェクトを比較して等しい場合、各オブジェクトの GetHashCode メソッドは同じ値を返す必要があります。ただし、2 つのオブジェクトが等しくない場合、2 つのオブジェクトの GetHashCode メソッドは異なる値を返す必要はありません。

あなたの観察はドキュメントと矛盾しておらず、実装にバグはありません。

于 2012-07-29T23:58:45.650 に答える