diff --git a/src/StringTools/InternableString.Simple.cs b/src/StringTools/InternableString.Simple.cs
index 7dd2b72b9ac..44955d274aa 100644
--- a/src/StringTools/InternableString.Simple.cs
+++ b/src/StringTools/InternableString.Simple.cs
@@ -200,29 +200,45 @@ public override unsafe string ToString()
/// A stable hashcode of the string represented by this instance.
public override int GetHashCode()
{
- int hashCode = 5381;
+ uint hash = (5381 << 16) + 5381;
+ bool isOddIndex = false;
if (_firstString != null)
{
foreach (char ch in _firstString)
{
- unchecked
- {
- hashCode = hashCode * 33 ^ ch;
- }
+ hash = HashOneCharacter(hash, ch, isOddIndex);
+ isOddIndex = !isOddIndex;
}
}
else if (_builder != null)
{
for (int i = 0; i < _builder.Length; i++)
{
- unchecked
- {
- hashCode = hashCode * 33 ^ _builder[i];
- }
+ hash = HashOneCharacter(hash, _builder[i], isOddIndex);
+ isOddIndex = !isOddIndex;
}
}
- return hashCode;
+ return (int)hash;
+ }
+
+ ///
+ /// A helper to hash one character.
+ ///
+ /// The running hash code.
+ /// The character to hash.
+ /// True if the index of the character in the string is odd.
+ ///
+ private static uint HashOneCharacter(uint hash, char ch, bool isOddIndex)
+ {
+ if (isOddIndex)
+ {
+ // The hash code was rotated for the previous character, just xor.
+ return hash ^ ((uint)ch << 16);
+ }
+
+ uint rotatedHash = (hash << 5) | (hash >> (32 - 5));
+ return (rotatedHash + hash) ^ ch;
}
}
}