2010-05-26 22 views

cevap

3

için var mıdır apache karma kodudur üstlenici firmanın çok

kullanmak kullandı: Böyle bir yardımcı, hızlı kullanımı kolaydır

public static int ComputeHashFrom(params object[] obj) { 
    ulong res = 0; 
    for(uint i=0;i<obj.Length;i++) { 
     object val = obj[i]; 
     res += val == null ? i : (ulong)val.GetHashCode() * (1 + 2 * i); 
    } 
    return (int)(uint)(res^(res >> 32)); 
} 

ve Güvenilir, ancak potansiyel olarak iki downsides (sık sık rastlanamayacaksınız, ancak farkında olmak için iyi) vardır:

  • Bazı paramik dağılımları için zayıf şifreler üretebilir. Örneğin, herhangi bir int x, ComputeHashFrom(x*-3, x) == 0 için - eğer nesneleriniz belirli bir patolojik özelliklere sahipse, sözlüklerin ve Hashsetlerin yetersiz performans göstermesiyle sonuçlanan birçok karma kod çarpışması alabilirsiniz. Olması muhtemel değildir, ancak tür farkındalık karma kod hesaplaması bu tür sorunları daha kolay önleyebilir.
  • Hash kodunun hesaplanması, özel bir hesaplamadan daha yavaştır. Özellikle, params dizisinin tahsisini ve bir döngüyü içeriyordu - bu işlem için sadece iki üyeye sahip olmanız durumunda oldukça fazla gereksiz ek yük.

Bu dezavantajların hiçbiri yalnızca verimsizliğe neden olur; ve her ikisi de bir profilerde bu yöntemde veya karma kod tüketicisinin içeriğinde blips olarak gösterilir.

+0

Hızla ilgili uyarılarınız için, özellikle neyin mantıklı olduğuna dair bir fikriniz varsa, tür bilinci olan bir yöntemle daha iyi karma kodlar üretebileceğinizi de eklemeliyim. değerler en sık gerçekleşecek. Bunun hakkında daha fazla bilgi sahibi olmak için hesaplama hızına bakacağım. –

+0

Böyle basit ve güvenli bir yöntemin amacı basit ve güvenlidir. Nesnelerin bazı dağılımları için, bu, daha kötü karma kodlarla sonuçlanacak ve her zaman hesaplamak için biraz daha zaman alacak. Bununla birlikte, genel durumda, bu karmaşaklar iyi çalışır (sonuçta, kurucu üyeler genellikle türden haberdar GetHashCode uygulamalarına sahiptirler) ve çoğu program zamanlarının çoğunu karma kodları kullanarak veya harcayarak geçirmez. Bununla birlikte, pratik deneyimden, GetHashCode perf sorunlarına girdiğimi, ancak * bu * uygulama - YMMV ile kalite sorunlarına girmediğimi hatırlayacağım. –

+0

Uygulamada, nesne eşitliği karşılaştırması genellikle '.GetHashCode''dan çok daha ucuz olduğundan, bir kaç * daha fazla çarpışma ile karşılaşırsanız çok az para ödersiniz. Diğer yandan, çok fazla set/sözlük hesaplaması yapıyorsanız, değişmemiş nesnelerin hash kodunu kolayca önbelleğe alabilirsiniz; fakat kötü bir karma kodun sonuçlarından kaçınamazsınız. Her neyse, pratikte profillemenin buna değmeyene kadar daha karmaşık bir şeyle uğraşmayacağım - ki neredeyse hiç yapmadı. –

1

C# yerleşik bir HashCode geliştiricisine sahip değil, ancak kendi kendinize yuvarlanabiliyorsunuz, son zamanlarda bu kadar hassas bir sorunla karşılaştım ve genetiği kullanarak boks kullanmıyor olan bu karma kod üretecini oluşturdu ve değiştirilmiş bir araç uygular. FNV (Fowler/Noll/Vo Hash) belirli karma üretmek için, ancak bu benim ev yapımı kurucusudur System.Security.Cryptography

public static int GetHashCode<T>(params T[] args) 
    { 
     return args.GetArrayHashCode(); 
    } 

    public static int GetArrayHashCode<T>(this T[] objects) 
    { 
     int[] data = new int[objects.Length]; 

     for (int i = 0; i < objects.Length; i++) 
     { 
      T obj = objects[i]; 
      data[i] = obj == null ? 1 : obj.GetHashCode(); 
     } 

     return GetFnvHash(data); 
    } 

    private static int GetFnvHash(int[] data) 
    { 
     unchecked 
     { 
      const int p = 16777619; 
      long hash = 2166136261; 

      for (int i = 0; i < data.Length; i++) 
      { 
       hash = (hash^data[i]) * p; 
      } 

      hash += hash << 13; 
      hash ^= hash >> 7; 
      hash += hash << 3; 
      hash ^= hash >> 17; 
      hash += hash << 5; 

      return (int)hash; 
     } 
    } 
2

içinde Algoritmalar biri gibi istediğiniz başka herhangi bir algoritma, kullanabilirsiniz .

Kullanımı:

hash = new HashCodeBuilder(). 
      Add(a). 
      Add(b). 
      Add(c). 
      Add(d). 
      GetHashCode(); 

dizi oluşturmak için, gerek uzatmak için ne tür alanları a, b, c ve d vardır, kolay fark etmez.

Kaynak:

public sealed class HashCodeBuilder 
{ 
    private int hash = 17; 

    public HashCodeBuilder Add(int value) 
    { 
     unchecked 
     { 
      hash = hash * 31 + value; //see Effective Java for reasoning 
      // can be any prime but hash * 31 can be opimised by VM to hash << 5 - hash 
     } 
     return this; 
    } 

    public HashCodeBuilder Add(object value) 
    { 
     return Add(value != null ? value.GetHashCode() : 0); 
    } 

    public HashCodeBuilder Add(float value) 
    { 
     return Add(value.GetHashCode()); 
    } 

    public HashCodeBuilder Add(double value) 
    { 
     return Add(value.GetHashCode()); 
    } 

    public override int GetHashCode() 
    { 
     return hash; 
    } 
} 

Örnek kullanım: burada üfürüm ve XXHash ait

public sealed class Point 
{ 
    private readonly int _x; 
    private readonly int _y; 
    private readonly int _hash; 

    public Point(int x, int y) 
    { 
     _x = x; 
     _y = y; 
     _hash = new HashCodeBuilder(). 
      Add(_x). 
      Add(_y). 
      GetHashCode(); 
    } 

    public int X 
    { 
     get { return _x; } 
    } 

    public int Y 
    { 
     get { return _y; } 
    } 

    public override bool Equals(object obj) 
    { 
     return Equals(obj as Point); 
    } 

    public bool Equals(Point other) 
    { 
     if (other == null) return false; 
     return (other._x == _x) && (other._y == _y); 
    } 

    public override int GetHashCode() 
    { 
     return _hash; 
    } 
} 
+0

Yeniden kullanılabilir kodun kapsülleme kavramını beğeniyorum. Ancak yöntem çağrıları nedeniyle bir performans cezası yok mu? –

+1

@SteveB Nasıl kullandığınıza bağlı. Dikkat edilirse, ideal olarak sadece karma kodlarda immutable verileri kullanmalısınız, eğer bunu bir kez yapıcıda yaparsanız, o zaman sonucu özel üye 'hash' içinde saklayın, her zaman GetHashCode 'çağrıldığında normal hesaplamayı yapmaktan daha etkilidir. – weston

+0

@SteveB Ne demek istediğimi göstermek için örnek kullanım eklendi. Ayrıca doğru eşit uygulama vardır. – weston

İlgili konular