Table of Contents

Class StableHash

Namespace
The.Caching
Assembly
Instagile.dll

Utility methods for persisted cache keys.

public static class StableHash
Inheritance
StableHash
Inherited Members

Remarks

Everything here is deterministic across processes, runtimes and .NET versions (on little-endian platforms), because the results are persisted. Hash values are a serialisation contract: changing them requires a CacheFile format version bump. The golden tests pin them.

Methods

Combine(int, int)

Stably combines two hash codes, a fixed-seed counterpart to Combine<T1, T2>(T1, T2).

public static int Combine(int hash1, int hash2)

Parameters

hash1 int
hash2 int

Returns

int

Combine(int, int, int)

Stably combines three hash codes, a fixed-seed counterpart to Combine<T1, T2, T3>(T1, T2, T3).

public static int Combine(int hash1, int hash2, int hash3)

Parameters

hash1 int
hash2 int
hash3 int

Returns

int

ForBytes(ReadOnlySpan<byte>)

Produces a stable hash code for raw bytes using the Marvin32 algorithm with a fixed seed.

public static int ForBytes(ReadOnlySpan<byte> data)

Parameters

data ReadOnlySpan<byte>

Returns

int

ForGuid(Guid)

Produces a stable hash code for a guid, independent of GetHashCode().

public static int ForGuid(Guid guid)

Parameters

guid Guid

Returns

int

ForString(string?)

Produces a stable hash code using the Marvin32 algorithm (which GetHashCode() does not).

public static int ForString(string? str)

Parameters

str string

Returns

int

Remarks

This implementation is based on .NET's Marvin hashing algorithm but uses a fixed seed to ensure stability. .NET's string.GetHashCode() uses a randomized seed to prevent hash-based attacks, but we need stable hashes for caching.

ForValue(object?)

Produces a stable hash code for a query constant, covering the closed domain of value types the query analyzer admits: the ValueBox types, RelativeDate, enums, and sequences of any of these. Values outside the domain fall back to their own GetHashCode(), which is process-local.

public static int ForValue(object? value)

Parameters

value object

Returns

int

Remarks

Equal values must hash equal, so each recipe follows its type's equality semantics: DateTime equality ignores Kind, DateTimeOffset equality compares UTC instants, -0.0 equals 0.0, NaN equals NaN, and numerically-equal decimals of different scale are equal.