2012-03-14 15 views
9

Özdeş özdeşlik değerlerine sahip iş nesnelerinin eşit olduğu anlamını uygulamak için kendi kimliğimi Equals() ve GetHashCode() sık sık buluyorum. Bu, yazma ve yazma için kırılgan yinelenen kod yol açar (özellik eklenir ve geçersiz kılmaların biri/her ikisi de güncelleştirilmez).Daha İyi Bakımı için C# 'da Eşittir(), GetHashCode()' ı Geçersiz Kılmayı Basitleştirin

kod aşağıdaki gibi görünen biter (uygulanmasına ilişkin yorumlarınızı bekliyoruz):

public override bool Equals(object obj) 
{ 
    if (object.ReferenceEquals(this, obj)) return true; 

    MyDerived other = obj as MyDerived; 

    if (other == null) return false; 

    bool baseEquals = base.Equals((MyBase)other); 
    return (baseEquals && 
     this.MyIntProp == other.MyIntProp && 
     this.MyStringProp == other.MyStringProp && 
     this.MyCollectionProp.IsEquivalentTo(other.MyCollectionProp) && // See http://stackoverflow.com/a/9658866/141172 
     this.MyContainedClass.Equals(other.MyContainedClass)); 
} 

public override int GetHashCode() 
{ 
    int hashOfMyCollectionProp = 0; 
    // http://computinglife.wordpress.com/2008/11/20/why-do-hash-functions-use-prime-numbers/ 
    // BUT... is it worth the extra math given that elem.GetHashCode() should be well-distributed? 
    int bitSpreader = 31; 
    foreach (var elem in MyCollectionProp) 
    { 
     hashOfMyCollectionProp = spreader * elem.GetHashCode(); 
     bitSpreader *= 31; 
    } 
    return base.GetHashCode()^//^is a good combiner IF the combined values are well distributed 
     MyIntProp.GetHashCode()^
     (MyStringProp == null ? 0 : MyStringProp.GetHashValue())^
     (MyContainedClass == null ? 0 : MyContainedClass.GetHashValue())^
     hashOfMyCollectionProp; 
} 

Sorularım

  1. mi uygulama desen ses?
  2. Katkıda bulunan bileşen değerlerinin iyi dağıtıldığı dikkate alındığında yeterli midir? Tahıl öğelerinin iyi bir şekilde dağıtılması durumunda toplama öğelerini birleştirirken 31 N'ye çarpmak zorunda mıyım?
  3. Bu kod, ortak özellikleri belirlemek için yansıma kullanan, el ile kodlanmış çözümle eşleşen bir ifade ağacı oluşturan ve ifade ağacını gerektiği şekilde yürüten bir kodla soyutlanmış gibi görünüyor. Bu yaklaşım makul görünüyor mu? Bir yerde var olan bir uygulama var mı?
+2

olmalıdır Neden (yazdıktan sonra bir yıldan fazla) downvote? Soru çok meşrudur. Eğer yanlış bir şey varsa, lütfen ne olduğunu söyle. –

cevap

4

MSDN aslında söylemez yok "aşırı yük değişken türleri için diğ Eşittir yok". O öyle derdi, ama şimdi diyor ki: Eğer bir sınıf veya yapı tanımladığınızda

, bunu tip değeri eşitlik (veya denklik) özel bir tanımını oluşturmak mantıklı yapar karar verir. Tipik olarak, türünün nesnelerinin bir çeşit koleksiyona eklenmesi bekleniyorsa veya temel amaçları bir dizi alan veya özellik saklamak olduğunda değer eşitliğini uygularsınız.

http://msdn.microsoft.com/en-us/library/dd183755.aspx

Yine de, bir amacı, bir karma toplama ( Dictionary<T,U>, HashSet<T>, vs.) katılır ise karma kodu stabilitesini çevreleyen karmaşıklığı vardır.Burada belirtildiği gibi

Ben, her iki dünyanın en iyi için tercih verdi:

https://stackoverflow.com/a/9752155/141172

1

Sık sık

  • MSDN diyor benim öz geçersiz kılma eşittir bulmak() ve GetHashCode(): do aşırı yük değişken türleri

için diğ Eşittir değil Katkıda bulunan bileşen değerlerinin iyi dağıtıldığı dikkate alındığında yeterli midir?

  • Evet, ama hey her zaman iyi dağıtılmış değildir. int özelliklerini göz önünde bulundurun. Bazı (küçük) asal sayılarla geçiş yapılması tavsiye edilir.
+0

MSDN nerede diyor? Metni tam anlamıyla incelemeye çalıştım ve sadece bu soruyu buldum. –

+0

Ayrıca ... (Ben bir şey eksik) overriding yardımcı programı görüyorum nerede basit bir örnek almak için nasıl bir eşitlik uygulamıyor Eşittir geçersiz bir birim testi uygulamak mı? MyDerived beklenen = yeni MyDerived() {/* Başlatma * /}; MyDerived asıl = DoSomeTest(); Assert.AreEqual (beklenen, gerçek) '? –

+0

Ve^ile ilgili olarak ... benim durumumda, her bir XORed değeri, makul bir şekilde dağıtılması gereken GetHashCode() sonucudur. Uygulandığı gibi,^kullandığım kusurları görüyor musunuz? Her koleksiyon öğesinin karması GetHashCode() sonucunun bir sonucu olsa bile koleksiyon öğelerini bir asal çarpar mı? –

0

Belki burada kafam karıştı ama null çeke bir 0 yerine 1 dönmek olmamalıdır GetHashCode geçersiz kılma?

Yani

MyStringProp == null ? 0 : MyStringProp.GetHashValue() 

MyStringProp == null ? 1 : MyStringProp.GetHashValue() 
İlgili konular