Взгляните на исходный код string.GetHashCode
, используя Reflector показывает следующее (для версии mscorlib.dll 4.0):
public override unsafe int GetHashCode()
{
fixed (char* str = ((char*) this))
{
char* chPtr = str;
int num = 0x15051505;
int num2 = num;
int* numPtr = (int*) chPtr;
for (int i = this.Length; i > 0; i -= 4)
{
num = (((num << 5) + num) + (num >> 0x1b)) ^ numPtr[0];
if (i <= 2)
{
break;
}
num2 = (((num2 << 5) + num2) + (num2 >> 0x1b)) ^ numPtr[1];
numPtr += 2;
}
return (num + (num2 * 0x5d588b65));
}
}
Теперь я понимаю, что реализация GetHashCode
не указана и зависит от реализации, поэтому вопрос "есть GetHashCode
реализованы в виде X или Y?" на самом деле не отвечает. Мне просто интересно несколько вещей:
- Если Reflector правильно разобрал DLL, и это реализация
GetHashCode
(в моей среде), могу ли я правильно интерпретировать этот код, чтобы указать, что объектstring
, основанный на этой конкретной реализации, не будет кэшировать его хеш-код? - Предполагая, что ответ да, почему это было бы? Мне кажется, что стоимость памяти будет минимальной (еще одно 32-битное целое число, падение пруда по сравнению с размером самой строки), тогда как экономия будет значительной, особенно в тех случаях, когда используются, например, строки как ключи в коллекции на основе хэш-таблицы, например,
Dictionary<string, [...]>
. А поскольку классstring
неизменен, это не похоже на то, что значение, возвращаемоеGetHashCode
, даже изменится.
Что я могу потерять?
ОБНОВЛЕНИЕ. В ответ на замечание Андраса Золтана:
Там также точка, сделанная в Тиме ответ (+1 там). Если он прав, а я думаю, что он есть, тогда нет никакой гарантии что строка фактически неизменяема после построения, поэтому кэшировать результат будет неправильным.
Эй, ага! Это интересный момент для создания (и да, это очень верно), но я действительно сомневаюсь, что это было принято рассмотрение при реализации GetHashCode
. Утверждение "поэтому для кэширования результата было бы неправильным" подразумевает, что отношение структуры к строкам "Ну, они должны быть неизменными, но на самом деле, если разработчики хотят получить подлый, они изменяемы, поэтому мы будем рассматривать их как таковых". Это определенно не то, как строки представления структуры. Он полностью полагается на их неизменность во многих отношениях (интернирование строковых литералов, назначение всех строк нулевой длины на string.Empty
и т.д.), Которые, в основном, если вы мутируете строку, вы пишете код, поведение которого полностью undefined и непредсказуемым.
Я предполагаю, что моя точка зрения заключается в том, что для автора (ов) этой реализации беспокоиться: "Что делать, если этот экземпляр строки изменен между вызовами, хотя класс, поскольку он публично открыт, является неизменным?" было бы похоже на то, что кто-то, планируя случайный открытый барбекю, подумает ему: "Что, если кто-то привнесет атомную бомбу в партию?" Послушайте, если кто-то приносит атомную бомбу, вечеринки.