public override int GetHashCode()
{
unchecked
{
return (str1 ?? String.Empty).GetHashCode() +
(str2 ?? String.Empty).GetHashCode();
}
}
Используя '+' оператор мог бы быть лучше, чем использование '^ ', потому что, хотя Вы явно хотите ('AA', 'BB') и ('BB', 'AA') явно быть тем же, Вы не можете хотеть ('AA', 'AA') и ('BB', 'BB') быть тем же (или все равные пары в этом отношении).
'максимально быстро' правило не полностью придерживается к в этом решении, потому что в случае пустых указателей это выполняет 'GetHashCode ()' на пустой строке, а не сразу возвратите известную константу, но даже явно не имея размеры я готов рисковать предположением, что различие не было бы достаточно большим для волнения о том, если Вы не ожидаете много пустых указателей.
Умножьте единицу на достаточно высокое значение
SELECT id1 * 1000000 + id2
Или используйте конкатенацию текста:
SELECT CAST(CAST(id1 AS nvarchar(10)) + RIGHT('000000' + CAST(id2 AS nvarchar(10)), 6) AS int)
Или пропустите целое число и разделите идентификаторы чем-то нечисловым:
SELECT CAST(id1 AS nvarchar) + ':' + CAST(id2 AS nvarchar)
Вы можете математически доказать, что это невозможно, если вы хотите, чтобы результирующий ключ содержал то же количество битов, что и два его компонента. Однако, если вы начнете с двух 32-битных int и можете использовать для результата 64-битное int, вы, очевидно, можете сделать что-то вроде этого:
key1 << 32 | key2
Вы можете сделать это, только если у вас есть верхняя граница для одного из ключей. Предположим, у вас есть key1
и key2
, а up1
- это значение, которое никогда не достигнет key1
, тогда вы можете комбинировать ключи следующим образом :
combined = key2 * up1 + key1;
Даже если ключи теоретически могут неограниченно расти, обычно на практике можно оценить верхнюю границу сохранения.
Оба предлагаемых решения требуют некоторых знаний о диапазоне принимаемых ключей.
Чтобы избежать этого предположения, можно перемешать цифры вместе.
Key1 = ABC => Digits = A, B, C
Key2 = 123 => Digits = 1, 2, 3
Riffle (Key1, Key2) = A, 1, B, 2, C, 3
Если не хватает цифр, можно использовать заполнение нулями:
Key1 = 12345, Key2 = 1 => 1020304051
Этот метод также универсален для любого количества ключей.
Рискну показаться шутливым:
NewKey = fn(OldKey1, OldKey2)
где fn () - это функция, которая ищет новое значение ключа с автоматической нумерацией из столбца, добавленного к существующей таблице.
Очевидно, два Целочисленные поля могут содержать экспоненциально больше значений, чем одно целочисленное поле.
Почему бы вам просто не использовать ROW_NUMBER () или IDENTITY (int , 1,1) установить новый ID? Они ДЕЙСТВИТЕЛЬНО должны быть в отношениях?
Поскольку мне нравится теоретическая сторона вашего вопроса (она действительно прекрасна), и чтобы опровергнуть то, что говорят многие практические ответы, я хотел бы дать ответ на «математическую» часть ваших тегов :)
Фактически возможно сопоставить любые два числа (или фактически любую серию чисел) одному числу. Это число называется числом Гёделя и было впервые опубликовано в 1931 году Куртом Гёделем.
Чтобы дать быстрый пример, с вашим вопросом; скажем, у нас есть две переменные v1 и v2. Тогда v3 = 2 v1 * 3 v2 даст уникальный номер. Этот номер также однозначно идентифицирует v1 и v2.
Конечно, результирующее число v3 может расти нежелательно быстро. Пожалуйста, примите этот ответ как ответ на теоретический аспект вашего вопроса.
This has been discussed in a fair amount of detail already (as recursive said, however, the output must be comprised of more bits than the individual inputs).
Mapping two integers to one, in a unique and deterministic way
How to use two numbers as a Map key
http://en.wikipedia.org/wiki/Cantor_pairing_function#Cantor_pairing_function