2012-12-20 26 views
7

Ho avuto numerosi casi in cui ho bisogno di accedere ad un algoritmo di hashing decente in C#, dall'overriding GetHashCode all'esecuzione di confronti rapidi/ricerche sui dati.Implementazione C# di FNV Hash

Ho trovato che l'hash FNV è un algoritmo hash veramente facile/buono/veloce. Tuttavia, non ho mai visto un buon esempio di implementazione C#.

Il nucleo della algoritmo di hash FNV-1a è la seguente:

hash = OFFSET_BASIS 
foreach (object value in object) 
{ 
    hash = hash^value.GetHashCode() 
    hash = hash * FNV_PRIME 
} 

Così, quando sovrascrivo GetHashCode per una classe finisco per fare qualcosa di simile:

public static class FNVConstants 
{ 
    public static readonly int OffsetBasis = unchecked((int)2166136261); 
    public static readonly int Prime = 16777619; 
} 

public override int GetHashCode() 
{ 
    int hash = Constants.FNVConstants.OffsetBasis; 
    hash = (hash^EntityId.GetHashCode()) * Constants.FNVConstants.Prime; 
    hash = (hash^FromDate.GetHashCode()) * Constants.FNVConstants.Prime; 
    hash = (hash^ToDate.GetHashCode()) * Constants.FNVConstants.Prime; 
    return hash; 
} 

Che cosa la gente pensa a questo?

+2

Si guarda bene a me ... si shoudl proprio vicino 'hash^x' tra parentesi - per esempio '(hash^x) * primo' - altrimenti la moltiplicazione verrà eseguita per prima. – digEmAll

risposta

7

Si potrebbe aggiungere questo alla vostra classe FNVConstants

public static int CreateHash(params object[] objs) 
{ 
    return objs.Aggregate(OffsetBasis, (r, o) => (r^o.GetHashCode()) * Prime); 
} 

Poi chiamarlo come

public override int GetHashCode() 
{ 
    return FNVConstants.CreateHash(EntityId, FromDate, ToDate); 
} 
+0

bello. Non ho mai pensato di usare Linq per qualcosa del genere, ma ha perfettamente senso. Piccolo, conciso. :) Grazie – Keith

+4

GetHashCode non deve mai allocare memoria nell'heap. –

+0

Eh? Dove assegna mai memoria nell'heap? – Keith