ポイントは、object.GetHashCode()
オーバーライドできることです-そして、多くの場合、string
. つまり、デフォルトの実装がobject.GetHashCode()
返す「ID ハッシュ コード」を見つけることができません。
これは、オブジェクトの同一性のみを考慮する等価比較子 (たとえば aHashSet
など)を実装する場合に役立ちます。
例えば:
public class IdentityComparer<T> : IEqualityComparer<T> where T : class
{
public bool Equals(T x, T y)
{
// Just for clarity...
return object.ReferenceEquals(x, y);
}
public int GetHashCode(T x)
{
// The nullity check may be unnecessary due to a similar check in
// RuntimeHelpers.GetHashCode, but it's not documented
return x == null ? 0 : RuntimeHelpers.GetHashCode(x);
}
}
それで:
string x = "hello";
string y = new StringBuilder("h").Append("ello").ToString();
Console.WriteLine(x == y); // True (overloaded ==)
Console.WriteLine(x.GetHashCode() == y.GetHashCode()); // True (overridden)
IdentityComparer<string> comparer = new IdentityComparer<string>();
Console.WriteLine(comparer.Equals(x, y)); // False - not identity
// Very probably false; not absolutely guaranteed (as ever, collisions
// are possible)
Console.WriteLine(comparer.GetHashCode(x) == comparer.GetHashCode(y));
編集:少し明確にするために...
では、RuntimeHelpers.GetHashCode(object) の実際の動作はどのようなもので、どのように機能するのでしょうか?
観測された動作は、 から返されるRuntimeHelpers.GetHashCode(object)
値が への非仮想呼び出しから返される値と同じであるということObject.GetHashCode()
です。(その非仮想呼び出しを C# で簡単に作成することはできません。)
それがどのように機能するかについて-それは実装の詳細です:) IMOがどちらの方法で発生するか(何が何を呼び出すか)は実際には問題ではありません。重要なことは、文書化された動作です。これは正しいです。mscorlib の異なるバージョンでは、これを異なる方法で実装できます。ユーザーの観点からはまったく問題になりません。逆コンパイルしないと、違いがわからないはずです。
Object.GetHashCode
(IMO)の観点から文書化されていたのは、はるかに混乱していたでしょうRuntimeHelpers.GetHashCode()
。