更新:以下の私の元の分析は間違っていました...
残念ながら、<< 32
C# では、左シフト演算子が右オペランドの下位 5 ビット (64 ビットの左オペランドを含むシフトの場合は 6 ビット) にシフト数を制限することが強制されます。したがって、元のコードは C# で明確に定義され、正しいものでした (C/C++ では未定義の動作です)。基本的に、このシフト式:
(this.Array[i] << shift)
次と同等です。
(this.Array[i] << (shift & 0x1f))
if (shift == 32)
チェックの代わりに上記を使用して、おそらくシフトを変更してそれを明示するでしょう(6か月後にそのコードを見たときに同じ間違った分析につまずくことがないという他の理由がなければ) 。
元の分析:
では、2 番目の回答を次に示します。最も重要なことは、最後の配列要素が異なる2つの配列に対してImmutableBitArray
返されるビット長が32ビットの倍数である場合、元のソリューションにバグがあると思います。true
Int32[]
たとえば、ImmutableBitArray
異なるビット長 32 ビットの s を考えてみましょう。元のEquals()
方法では、配列内の唯一のシフト操作を実行しInt32
ますが、値を 32 ビットシフトします。
int shift = 0x20 - (this.length % 0x20);
32 に評価されます。
つまり、次のテストです。
if (this.Array[i] << shift != other.Array[i] << shift)
をテストする(0 != 0)
ため、return false
は実行されません。
あなたのEquals()
方法を次のようなものに変更しますが、これは大きな変更ではありません-上記のバグを処理し、厳密にスタイルに関連する他のいくつかのことを変更すると思いますので、あなたには興味がないかもしれません. また、メソッドを実際にコンパイルしてテストしていないことにも注意してください。そのEquals()
ため、バグ (または少なくとも構文エラー) がある可能性はほぼ 100% です。
public bool Equals(ImmutableBitArray other)
{
if (this.length != other.length)
{
return false;
}
int finalIndex = this.Array.Length - 1;
for (int i = 0; i < finalIndex; i++)
{
if (this.Array[i] != other.Array[i])
{
return false;
}
}
// check the last array element, making sure to ignore padding bits
int shift = 32 - (this.length % 32);
if (shift == 32) {
// the last array element has no padding bits - don't shift
shift = 0;
}
if (this.Array[finalIndex] << shift != other.Array[finalIndex] << shift)
{
return false;
}
return true;
}
厳密に言えば、GetHashCode()
同じ欠陥があっても元のメソッドにはバグがないことに注意してください。ビット長が 32 の倍数であるときに最後の要素を適切に混合しなくても、等しいオブジェクトは依然として同じハッシュコード。しかし、私はおそらく、同じ方法でGetHashCode()
.