簡単な質問
GetHashCode
にArray
を実装する方法。
詳細
Equals
をオーバーライドするオブジェクトがあり、次のことを確認しています。
this.array[n] == otherObject.array[n]
n
内のすべてのarray
に対して。
当然、補完的なGetHashCode
を実装する必要があります。これを行うための.NETの方法があるのか、それとも自分で実装する必要があるのか、
hash = hash ^ array[n]
説明
私のオブジェクトには配列が含まれており、配列の要素のGetHashCodeに興味があります。配列の同等性に関する私のコードは、たとえば、私の質問が言うように、はっきりしていなかったかもしれませんが、GetHashCode
(Equals
ではありません)に興味があります。 GetHashCode
がオーバーライドされたら(Equals
などが正しく機能するために)これを実装することは.NETの要件であるため、当然、補完的なDictionary
を実装する必要があると言います。ありがとう。
配列の要素を使用してハッシュコードを計算するには、配列を IStructuralEquatable にキャストしてから、 GetHashCode(IEqualityComparer) メソッドを呼び出し、次のタイプの比較子を渡します。配列内の要素。
(Arrayクラスはメソッドを明示的に実装するため、キャストが必要です。)
たとえば、オブジェクトにint
配列がある場合、次のようにGetHashCodeを実装できます。
public override int GetHashCode()
{
return ((IStructuralEquatable)this.array).GetHashCode(EqualityComparer<int>.Default);
}
興味がある場合は、ArrayクラスがGetHashCodeメソッドを実装する方法を次に示します( 参照ソース から):
internal static int CombineHashCodes(int h1, int h2) {
return (((h1 << 5) + h1) ^ h2);
}
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(i)));
}
return ret;
}
ご覧のとおり、現在の実装では配列の最後の8つの要素のみが使用されています。
GetHashCodeを配列に自然に実装する必要があることに同意しません
変更のたびに更新する必要があります
またはその場で計算する
その場で直接比較します
SequenceEqualsはデフォルトの等式比較子を使用するため、実装する必要があります
public bool Equals
0nオブジェクトin配列
Enumerable.SequenceEqual
例があります
public static void SequenceEqualEx1()
{
Pet pet1 = new Pet { Name = "Turbo", Age = 2 };
Pet pet2 = new Pet { Name = "Peanut", Age = 8 };
// Create two lists of pets.
List<Pet> pets1 = new List<Pet> { pet1, pet2 };
List<Pet> pets2 = new List<Pet> { pet1, pet2 };
bool equal = pets1.SequenceEqual(pets2);
Console.WriteLine(
"The lists {0} equal.",
equal ? "are" : "are not");
}
それはあなたが望むものに依存します...
Michaelが上記で回答した1つのオプションは、配列要素に基づくハッシュコードを持つことです。これは、Equals値のセマンティクスと一致します。ただし、「ガイドラインとして、オブジェクトのハッシュはオブジェクトの存続期間全体にわたって同じである必要がある」ため、ハッシュコードを取得した後に配列が変更されないようにする必要があります。変更されないことを要求する不変のコンテナを持つことは、私にはエラーが発生しやすいように聞こえます。
もう1つ(IMOのより良いオプション)は、不変のコンテナー(つまり、ImmutableArray)に切り替えることです。そうすれば、値ベースのハッシュコードが理にかなっています。上記のようにIStructuralEquatable
を使用するか、より一般的に使用できます。
public override GetHashCode() =>
Value.Aggregate(0, (total, next) => HashCode.Combine(total, next));
これは他の不変のコレクションでも機能します。
現在のフレームワークを使用すると、使用を検討できます
int value=0;
for (var i = 0;i< this.array.Length; i++)
{
value=HashCode.Combine(this.array[i],value);
}