StringBuilderExtensionGetPersistentHashCode Method

Generates the same Int32 hash code for an identical string of characters each time the program is run.

Definition

Namespace: FolkerKinzel.Strings
Assembly: FolkerKinzel.Strings (in FolkerKinzel.Strings.dll) Version: 9.4.0+10a7d4d71aa960998e32ac0ac6c4fcbe4164c917
C#
public static int GetPersistentHashCode(
	this StringBuilder builder,
	HashType hashType
)

Parameters

builder  StringBuilder
The Char sequence to be hashed.
hashType  HashType
The kind of hashcode to be generated.

Return Value

Int32
The hashcode.

Usage Note

In Visual Basic and C#, you can call this method as an instance method on any object of type StringBuilder. When you use instance method syntax to call this method, omit the first parameter. For more information, see Extension Methods (Visual Basic) or Extension Methods (C# Programming Guide).

Remarks

The method String.GetHashCode() returns a different hash code for an identical string with each program run for security reasons. Apart from the fact that the hash algorithm of String.GetHashCode() could be different in different framework versions, it makes no sense to use the return value of GetHashCode for reuse. The alternatives, e.g. MD5 or SHA256, use more storage space and are slower. This method offers a slim alternative that is suitable for hashing very short strings that are not used in a security-critical context.

The hashcode generated by this method is not identical to the hashcode generated by the .NET Framework 4.0, because it uses roundshifting to preserve more information.

The hashcodes generated with different values for hashType may provide different hashcodes for an identical Char sequence and MUST therefore not be mixed.

Do not use the hashcodes generated by this method for security-critical purposes (such as hashing passwords)!

Example

C#
using System;
using System.Text;
using FolkerKinzel.Strings;

namespace Examples
{
    public static class Example
    {
        public static void CreatePersistentStringHashes()
        {
            const string s1 = "Hello Folker!";
            const string s2 = "HELLO FOLKER!";
            const string s3 = "&: !heL##Lof OLker *";

            const string ind = "  ";

            Console.WriteLine($"{nameof(s1)}: {s1}");
            Console.WriteLine($"{nameof(s2)}: {s2}");
            Console.WriteLine($"{nameof(s3)}: {s3}");
            Console.WriteLine();

            // The extension method GetPersistentHashCode() produces identical Int32 hash codes for identical
            // Char sequences everytime it is called - even on String, StringBuilder or ReadOnlySpan<char>:
            Console.WriteLine("Ordinal:");
            Console.WriteLine($"{ind}{nameof(s1)}: {s1.GetPersistentHashCode(HashType.Ordinal):X8}");
            Console.WriteLine($"{ind}{nameof(s2)}: {s2.GetPersistentHashCode(HashType.Ordinal):X8}");
            Console.WriteLine($"{ind}{nameof(s3)}: {s3.GetPersistentHashCode(HashType.Ordinal):X8}");

            Console.WriteLine("OrdinalIgnoreCase:");
            Console.WriteLine(
                $"{ind}{nameof(s1)}: {s1.AsSpan().GetPersistentHashCode(HashType.OrdinalIgnoreCase):X8}");
            Console.WriteLine(
                $"{ind}{nameof(s2)}: {s2.GetPersistentHashCode(HashType.OrdinalIgnoreCase):X8}");
            Console.WriteLine(
                $"{ind}{nameof(s3)}: {s3.GetPersistentHashCode(HashType.OrdinalIgnoreCase):X8}");

            Console.WriteLine("AlphanumericIgnoreCase:");
            Console.WriteLine(
                $"{ind}{nameof(s1)}: {s1.AsSpan().GetPersistentHashCode(HashType.AlphaNumericIgnoreCase):X8}");
            Console.WriteLine(
                $"{ind}{nameof(s2)}: {new StringBuilder().Append(s2).GetPersistentHashCode(HashType.AlphaNumericIgnoreCase):X8}");
            Console.WriteLine(
                $"{ind}{nameof(s3)}: {s3.GetPersistentHashCode(HashType.AlphaNumericIgnoreCase):X8}");

            // Different HashTypes may produce different hashcodes on the same Char sequence
            // and MUST therefore not be mixed:
            Console.WriteLine("Same String - different HashTypes:");
            Console.WriteLine(
                $"{s1.GetPersistentHashCode(HashType.Ordinal),10:X08}");
            Console.WriteLine(
                $"{s1.GetPersistentHashCode(HashType.OrdinalIgnoreCase),10:X08}");
            Console.WriteLine(
                $"{s1.GetPersistentHashCode(HashType.AlphaNumericIgnoreCase),10:X08}");
        }
    }
}

/*
Console Output:

s1: Hello Folker!
s2: HELLO FOLKER!
s3: &: !heL##Lof OLker *

Ordinal:
  s1: A31FA6EC
  s2: 1BBFB34C
  s3: 364D7CD9
OrdinalIgnoreCase:
  s1: 1BBFB34C
  s2: 1BBFB34C
  s3: 12EF7A32
AlphanumericIgnoreCase:
  s1: C672C38C
  s2: C672C38C
  s3: C672C38C
Same String - different HashTypes:
  A31FA6EC
  1BBFB34C
  C672C38C
.
*/

Exceptions

ArgumentNullExceptionbuilder is null.
ArgumentExceptionhashType is not a defined value of the HashType enum.

See Also