この質問は、タプルに関する議論から生まれました。
タプルが持つべきハッシュコードについて考え始めました。KeyValuePair クラスをタプルとして受け入れるとどうなるでしょうか? GetHashCode() メソッドをオーバーライドしないため、おそらく「子」のハッシュ コードを認識しないでしょう...したがって、ランタイムは Object.GetHashCode() を呼び出しますが、これは認識されません。実際のオブジェクト構造。
次に、GetHashCode() と Equals() がオーバーロードされているため、参照型の 2 つのインスタンスを実際に Equal にすることができます。そして、それらをタプルの「子」として使用して、辞書を「ごまかす」。
しかし、うまくいきません!ランタイムはどうにかしてタプルの構造を理解し、クラスのオーバーロードされた GetHashCode を呼び出します!
それはどのように機能しますか?Object.GetHashCode() によって行われた分析は何ですか?
複雑なキーを使用する場合、悪いシナリオでパフォーマンスに影響を与える可能性はありますか? (おそらく、不可能なシナリオ...しかし、それでも)
次のコードを例として考えてみましょう。
namespace csharp_tricks
{
class Program
{
class MyClass
{
int keyValue;
int someInfo;
public MyClass(int key, int info)
{
keyValue = key;
someInfo = info;
}
public override bool Equals(object obj)
{
MyClass other = obj as MyClass;
if (other == null) return false;
return keyValue.Equals(other.keyValue);
}
public override int GetHashCode()
{
return keyValue.GetHashCode();
}
}
static void Main(string[] args)
{
Dictionary<object, object> dict = new Dictionary<object, object>();
dict.Add(new KeyValuePair<MyClass,object>(new MyClass(1, 1), 1), 1);
//here we get the exception -- an item with the same key was already added
//but how did it figure out the hash code?
dict.Add(new KeyValuePair<MyClass,object>(new MyClass(1, 2), 1), 1);
return;
}
}
}
更新以下の回答で説明されているように、これについての説明を見つけたと思います。その主な成果は次のとおりです。
- キーとそのハッシュ コードには注意してください :-)
- 複雑な辞書キーの場合、Equals() と GetHashCode() を正しくオーバーライドする必要があります。