Joshua Yates

Joshua Yates

1588575300

Why does Visual Studio add "-1937169414" to a generated hash code computation?

If you use Visual Studio’s own refactoring menu to add a GetHashCode implementation to a class like this:

Generate GetHashCode menu

and select the only int property in the class:

Member selection screen

it generates this code on .NET Framework:

public override int GetHashCode()
{
    return -1937169414 + Value.GetHashCode();
}

(it generates HashCode.Combine(Value) on .NET Core instead, which I’m not sure if it involves the same value)

What’s special about this value? Why doesn’t Visual Studio use Value.GetHashCode() directly? As I understand, it doesn’t really affect hash distribution. Since it’s just addition, consecutive values would still accumulate together.

EDIT: I only tried this with different classes with Value properties but apparently property name affects the number generated. For instance, if you rename the property to Halue, the number becomes 387336856.

#c-sharp #visual-studio #vscode

What is GEEK

Buddha Community

If you look for -1521134295 in Microsoft’s repositories you’ll see that it appears quite a number of times

Most of the search results are in the GetHashCode functions, but they all have the following form

int hashCode = SOME_CONSTANT;
hashCode = hashCode * -1521134295 + field1.GetHashCode();
hashCode = hashCode * -1521134295 + field2.GetHashCode();
// ...
return hashCode;

The first hashCode * -1521134295 = SOME_CONSTANT * -1521134295 will be pre-multiplied during the generation time by the generator or during compilation time by CSC. That’s the reason for -1937169414 in your code

Digging deeper into the results reveals the code generation part which can be found in the function CreateGetHashCodeMethodStatements

const int hashFactor = -1521134295;

var initHash = 0;
var baseHashCode = GetBaseGetHashCodeMethod(containingType);
if (baseHashCode != null)
{
    initHash = initHash * hashFactor + Hash.GetFNVHashCode(baseHashCode.Name);
}

foreach (var symbol in members)
{
    initHash = initHash * hashFactor + Hash.GetFNVHashCode(symbol.Name);
}

As you can see the hash depends on the symbol names. In that function the constant is also called permuteValue, probably because after the multiplication the bits are permuted around somehow

// -1521134295
var permuteValue = CreateLiteralExpression(factory, hashFactor);

There are some patterns if we view the value in binary: 101001 010101010101010 101001 01001 or 10100 1010101010101010 10100 10100 1. But if we multiply an arbitrary value with that then there are lots of overlapping carries so I couldn’t see how it works. The output may also has different number of set bits so it’s not really a permutation

You can find the another generator in Roslyn’s AnonymousTypeGetHashCodeMethodSymbol which calls the constant HASH_FACTOR

//  Method body:
//
//  HASH_FACTOR = 0xa5555529;
//  INIT_HASH = (...((0 * HASH_FACTOR) + GetFNVHashCode(backingFld_1.Name)) * HASH_FACTOR
//                                     + GetFNVHashCode(backingFld_2.Name)) * HASH_FACTOR
//                                     + ...
//                                     + GetFNVHashCode(backingFld_N.Name)

The real reason for choosing that value is yet still unclear

Joshua Yates

Joshua Yates

1588575300

Why does Visual Studio add "-1937169414" to a generated hash code computation?

If you use Visual Studio’s own refactoring menu to add a GetHashCode implementation to a class like this:

Generate GetHashCode menu

and select the only int property in the class:

Member selection screen

it generates this code on .NET Framework:

public override int GetHashCode()
{
    return -1937169414 + Value.GetHashCode();
}

(it generates HashCode.Combine(Value) on .NET Core instead, which I’m not sure if it involves the same value)

What’s special about this value? Why doesn’t Visual Studio use Value.GetHashCode() directly? As I understand, it doesn’t really affect hash distribution. Since it’s just addition, consecutive values would still accumulate together.

EDIT: I only tried this with different classes with Value properties but apparently property name affects the number generated. For instance, if you rename the property to Halue, the number becomes 387336856.

#c-sharp #visual-studio #vscode