Этот вопрос возникает из обсуждения кортежей .
Я начал думать о хэш-коде, который должен иметь кортеж.
Что если мы примем класс KeyValuePair в качестве кортежа? Он не переопределяет метод GetHashCode (), поэтому, вероятно, он не будет знать о хэш-кодах своих «потомков» ... Итак, во время выполнения будет вызываться Object.GetHashCode (), который не знает о структура реального объекта.
Тогда мы можем сделать два экземпляра некоторого ссылочного типа, которые на самом деле равны, из-за перегруженных GetHashCode () и Equals (). И используйте их как «детей» в кортежах, чтобы «обмануть» словарь.
Но это не работает! Во время выполнения каким-то образом выясняется структура нашего кортежа и вызывается перегруженный 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 ().