2012-12-20 13 views
7

Miałem wiele przypadków, w których potrzebuję dostępu do przyzwoitego algorytmu mieszającego w C#, z nadpisywania GetHashCode do szybkiego porównywania/wyszukiwania danych.C# implementacja skrótu FNV

Znalazłem hash FNV za naprawdę łatwy/dobry/szybki algorytm mieszający. Jednak nigdy nie widziałem dobrego przykładu implementacji C#.

Rdzeniem algorytmu mieszania FNV-1a jest następujący:

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

Więc kiedy zastępują GetHashCode dla klasy I w końcu robi coś takiego:

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; 
} 

Co ludzie myśleć o tym?

+2

To wygląda dobrze do mnie ... no właśnie shoudl blisko 'hash^x' w nawiasy - np '(hash^x) * prime' - inaczej mnożenie zostanie wykonane jako pierwsze. – digEmAll

Odpowiedz

7

Można dodać do swojej klasy FNVConstants

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

Następnie nazwać jak

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

ładny. Nigdy nie myślałem o używaniu Linqa do czegoś takiego, ale ma to sens. Mały, zwięzły. :) Dzięki – Keith

+4

GetHashCode nigdy nie powinien przydzielać pamięci na stercie. –

+0

Huh? Gdzie w ogóle przydziela pamięć na stercie? – Keith