2011-06-21 21 views
3

對於C++,我一直使用Boost.Functional/Hash創建良好的散列值,而不必處理位移,XOR和素數。是否有任何庫爲C#/ .NET生成良好的(我不求最佳)哈希值?我將使用此實用程序來實現GetHashCode(),而不是加密哈希。爲.NET創建「良好」散列碼ala Boost.Functional/Hash

解釋,爲什麼我覺得這是非常有用的,這裏是它結合了(實現GetHashCode()方法時ofcourse一個非常常見的操作)的散列值boost::hash_combine實現:

seed ^= hash_value(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2); 

顯然,這種代碼沒有按不屬於執行GetHashCode(),因此應該在其他地方實施。

+1

你如何定義好散列?出於什麼目的?你爲什麼不喜歡'GetHashCode()'? – CodesInChaos

+0

我認爲你誤解了OP。他希望有一些像Boost.Functional/Hash *在'GetHashCode' *中使用它! –

+1

相關:http://stackoverflow.com/questions/263400/what-is-the-best-algorithm-for-an-overridden-system-object-gethashcode – CodesInChaos

回答

1

this question的回答包含一些類似於Boost.Functional/Hash的輔助類的例子。儘管如此,看上去沒有任何優雅。

我不知道任何真正的.NET庫提供等效。

-3

看看這個link,它描述了MD5哈希。 否則使用GetHashCode()。

+0

-1:這對於'MyType.GetHashCode()' – Richard

+0

將是非常昂貴的.OP不是在談論密碼散列,更像是由'GetHashCode'等使用的散列函數。http://msdn.microsoft.com/zh-cn/ -us /庫/ System.Object的。gethashcode.aspx – LukeH

+0

@Richard和@LukeH - 請仔細閱讀這個問題,他不想要一個最佳的解決方案,但一個很好的解決方案。 – Bibhu

1

除非你有非常具體的要求,你不需要從第一原則計算你的類型的哈希碼。而是結合域/屬性,你用平等確定的哈希碼中的簡單的方法之一,是這樣的:

int hash = field1.GetHashCode(); 
hash = (hash *37) + field2.GetHashCode(); 

(從§ 3.3.2 C# in Depth, 2nd Ed, Jon Skeet採取組合功能)。

+1

使用31而不是37. 37可能導致退化散列,因爲Dictionary有時選擇它作爲容量。 – CodesInChaos

+2

@CodeInChaose:我懷疑任何*值在整個系統被考慮時會有退化情況。隨意挑選更好的價值 - 在一個普遍的答案他們是基本上任意的。 – Richard

4

我不會爲此使用單獨的庫。如前所述,對於GetHashCode方法來說,快速和穩定是非常重要的。平時我喜歡寫行內實現,但它可能是實際使用一個輔助類是一個好主意:

internal static class HashHelper 
{ 
    private static int InitialHash = 17; // Prime number 
    private static int Multiplier = 23; // Different prime number 

    public static Int32 GetHashCode(params object[] values) 
    { 
     unchecked // overflow is fine 
     { 
      int hash = InitialHash; 

      if (values != null) 
       for (int i = 0; i < values.Length; i++) 
       { 
        object currentValue = values[i]; 
        hash = hash * Multiplier 
         + (currentValue != null ? currentValue.GetHashCode() : 0); 
       } 

      return hash; 
     } 
    } 
} 

這樣常見的哈希計算邏輯可用於:

public override int GetHashCode() 
{ 
    return HashHelper.GetHashCode(field1, field2); 
} 
0

爲了避免拳擊問題鏈使用通用的擴展方法上的Int32

public static class HashHelper 
{ 
    public static int InitialHash = 17; // Prime number 
    private static int Multiplier = 23; // Different prime number 

    [MethodImpl(MethodImplOptions.AggressiveInlining)] 
    public static Int32 GetHashCode<T>(this Int32 source, T next) 
    { 
     // comparing null of value objects is ok. See 
     // http://stackoverflow.com/questions/1972262/c-sharp-okay-with-comparing-value-types-to-null 
     if (next == null) 
     { 
      return source; 
     } 
     unchecked 
     { 
      return source + next.GetHashCode(); 
     } 
    } 

} 

那麼你的電話,你可以做

HashHelper 
    .InitialHash 
    .GetHashCode(field0) 
    .GetHashCode(field1) 
    .GetHashCode(field2);