Это намного сложнее, чем кажется на первый взгляд.Для начала присвойте значению key2 совершенно другую строку.Обратите внимание, что хеш-код остается прежним:
var k1 = new TheKey(17, "abc");
var k2 = new TheKey(17, "def");
System.Diagnostics.Debug.Assert(k1.GetHashCode() == k2.GetHashCode());
Что вполне допустимо, единственное требование к хеш-коду - то, что одно и то же значение создает тот же хеш-код. Разные значения не должны создавать разные хеш-коды.Это физически невозможно, поскольку хеш-код .NET может представлять только 4 миллиарда различных значений.
Расчет хеш-кода для структуры - сложная задача.Первое, что делает CLR, это проверяет, содержит ли структура какие-либо ссылки на ссылочный тип или есть ли пропуски между полями.Ссылка требует особого отношения, потому что эталонное значение является случайным.Это указатель, значение которого изменяется, когда сборщик мусора сжимает кучу.Пробелы в структуре структуры создаются из-за выравнивания.Структура с байтами и целыми числами имеет 3-байтовый промежуток между двумя полями.
Если ни один из этих случаев не имеет значения, то все биты в значении структуры значимы.CLR быстро вычисляет хэш, сохраняя 32 бита за раз.Это «хороший» хеш, все поля в структуре участвуют в хеш-коде.
Если структура имеет поля ссылочного типа или имеет пробелы, тогда необходим другой подход.CLR повторяет поля структуры и ищет то, которое можно использовать для генерации хеша.Используемое поле - это поле типа значения или ссылка на объект, которая не является нулевой.Как только он находит его, он берет хеш этого поля, перезаписывает его с указателем таблицы методов и завершает работу .
Другими словами, только одно полев структуре участвует в расчете хеш-кода.В вашем случае используется только поле id .Вот почему значение строкового члена не имеет значения.
Это неясный фактоид, о котором, очевидно, важно знать, если вы когда-нибудь оставите его в CLR для генерации хеш-кодов для структуры.Безусловно, лучшее, что нужно сделать, это просто никогда не делать этого.Если вам нужно, то не забудьте упорядочить поля в структуре, чтобы первое поле дало вам лучший хэш-код.В вашем случае просто поменяйте местами поля id и Name .
Еще один интересный трюк, код вычисления хорошего хеша содержит ошибку.Он будет использовать быстрый алгоритм, когда структура содержит System.Decimal.Проблема в том, что биты десятичного числа не являются репрезентативными для его числового значения.Попробуйте это:
struct Test { public decimal value; }
static void Main() {
var t1 = new Test() { value = 1.0m };
var t2 = new Test() { value = 1.00m };
if (t1.GetHashCode() != t2.GetHashCode())
Console.WriteLine("gack!");
}