Solo tengo curiosidad porque supongo que tendrá un impacto en el rendimiento. ¿Considera la cadena completa? Si es así, será lento en una cadena larga. Si solo considera parte de la cadena, tendrá un mal rendimiento (por ejemplo, si solo considera el comienzo de la cadena, tendrá un mal rendimiento si un HashSet contiene principalmente cadenas con la misma.
Asegúrese de obtener el código fuente de la Fuente de referencia cuando tenga preguntas como esta. Hay mucho más que lo que puedes ver en un descomstackdor. Elija el que coincida con su objective .NET preferido, el método ha cambiado mucho entre las versiones. Reproduciré la versión de .NET 4.5 aquí, recuperada de Source.NET 4.5 \ 4.6.0.0 \ net \ clr \ src \ BCL \ System \ String.cs \ 604718 \ String.cs
public override int GetHashCode() { #if FEATURE_RANDOMIZED_STRING_HASHING if(HashHelpers.s_UseRandomizedStringHashing) { return InternalMarvin32HashString(this, this.Length, 0); } #endif // FEATURE_RANDOMIZED_STRING_HASHING unsafe { fixed (char *src = this) { Contract.Assert(src[this.Length] == '\0', "src[this.Length] == '\\0'"); Contract.Assert( ((int)src)%4 == 0, "Managed string should start at 4 bytes boundary"); #if WIN32 int hash1 = (5381<<16) + 5381; #else int hash1 = 5381; #endif int hash2 = hash1; #if WIN32 // 32 bit machines. int* pint = (int *)src; int len = this.Length; while (len > 2) { hash1 = ((hash1 << 5) + hash1 + (hash1 >> 27)) ^ pint[0]; hash2 = ((hash2 << 5) + hash2 + (hash2 >> 27)) ^ pint[1]; pint += 2; len -= 4; } if (len > 0) { hash1 = ((hash1 << 5) + hash1 + (hash1 >> 27)) ^ pint[0]; } #else int c; char *s = src; while ((c = s[0]) != 0) { hash1 = ((hash1 << 5) + hash1) ^ c; c = s[1]; if (c == 0) break; hash2 = ((hash2 << 5) + hash2) ^ c; s += 2; } #endif #if DEBUG // We want to ensure we can change our hash function daily. // This is perfectly fine as long as you don't persist the // value from GetHashCode to disk or count on String A // hashing before string B. Those are bugs in your code. hash1 ^= ThisAssembly.DailyBuildNumber; #endif return hash1 + (hash2 * 1566083941); } } }
Posiblemente sea más de lo que esperaba, anotaré un poco el código:
Al examinar el código fuente (cortesía de ILSpy ), podemos ver que itera sobre la longitud de la cadena.
// string [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail), SecuritySafeCritical] public unsafe override int GetHashCode() { IntPtr arg_0F_0; IntPtr expr_06 = arg_0F_0 = this; if (expr_06 != 0) { arg_0F_0 = (IntPtr)((int)expr_06 + RuntimeHelpers.OffsetToStringData); } char* ptr = arg_0F_0; int num = 352654597; int num2 = num; int* ptr2 = (int*)ptr; for (int i = this.Length; i > 0; i -= 4) { num = ((num << 5) + num + (num >> 27) ^ *ptr2); if (i <= 2) { break; } num2 = ((num2 << 5) + num2 + (num2 >> 27) ^ ptr2[(IntPtr)4 / 4]); ptr2 += (IntPtr)8 / 4; } return num + num2 * 1566083941; }