2010-12-14 28 views
8

Bazı dize üyeleri, bazı çift üyeler ve bazı dizi nesneleri içeren bir sınıfa sahibim.Nesneleri karşılaştırma

Bu sınıfın iki nesnesini oluşturuyorum, bu nesneleri karşılaştırmanın en basit ve etkili yolu var mı ve bunların eşit olduğunu mu söylüyorsunuz? Baska öneri?

Karşılaştırma işlevi nasıl yazılacağını biliyorum, ancak zaman alıcı olacak. Eğer gerçekten bunu yapabilirsiniz

+2

Nesnelerin eşit olması için koşullarınız nelerdir? – BoltClock

+0

Temel olarak, bu dizgi üyelerindeki tüm değerler, çift üyeler ve dizi (ler) aynı olmalıdır! – siva

+1

http://stackoverflow.com/questions/506096/comparing-object-properties-in-c adresinin olası kopyası – RameshVel

cevap

11

tek yolu eşitlik için koşullar sağlandığında gerçek dönmek bool Object.Equals(object other) geçersiz, aksi takdirde yanlış döndürmektir. Ayrıca, Equals()'u geçersiz kıldığınızda dikkate aldığınız verilerin tümüyle hesaplanmış bir int değerini döndürmek için int Object.GetHashCode()'u geçersiz kılmanız gerekir.

Bir kenara göre, GetHashCode() için yapılan sözleşmenin, Equals() karşılaştırılırken true değerini döndürürken, dönüş değeri iki nesne için eşit olması gerektiğini belirtir. Bu, return 0;'un geçerli bir GetHashCode() uygulaması olduğu anlamına gelir, ancak sınıfınızın nesneleri sözlük anahtarları olarak kullanıldığında veya HashSet<T>'da depolandığında verimsizliklere neden olur.

ben eşitlik uygulamak yolu şu şekildedir:

public class Foo : IEquatable<Foo> 
{ 
    public bool Equals(Foo other) 
    { 
     if (other == null) 
      return false; 

     if (other == this) 
      return true; // Same object reference. 

     // Compare this to other and return true/false as appropriate. 
    } 

    public override bool Equals(Object other) 
    { 
     return Equals(other as Foo); 
    } 

    public override int GetHashCode() 
    { 
     // Compute and return hash code. 
    } 
} 

GetHashCode() uygulanması basit bir yolu birlikte size Equals() eşitlik için dikkate verilerin tümünün karma kodlarını XOR etmektir. Örneğin, sen eşitlik için karşılaştırma özellikleri string FirstName; string LastName; int Id; eğer gibi Yani, uygulama görünebilir: Genellikle değil geçersiz kılma yapmak

public override int GetHashCode() 
{ 
    return (FirstName != null ? FirstName.GetHashCode() : 0)^
     (LastName != null ? LastName.GetHashCode() : 0)^
     Id; // Primitives of <= 4 bytes are their own hash codes 
} 

ben eşitlik ilgilendiğim çoğu zaman olduğu gibi eşitlik operatörleri, sadece sözlük anahtarlarının veya koleksiyonlarının amaçları için. Sözdizimsel olarak daha az ayrıntılı olduğu için, referans ile değere göre daha fazla karşılaştırma yapabilecek olursanız, sadece eşitlik operatörlerini geçersiz kılmayı düşünürdüm. Ancak, size nesne üzerinde == veya != kullanan tüm yerleri değiştirmek için hatırlamak zorunda (Equals() sizin uygulanmasında dahil!) Object.ReferenceEquals() kullanmak veya object her iki işlenen döküm için. Bu iğrenç tuhaflık (eğer dikkatli değilseniz, eşitlik testinde sonsuz tekrarlara neden olabilir), bu operatörleri nadiren geçersiz kılmamın temel nedenlerinden biridir. Ne duymak istediğiniz cevabı olmayabilir, ama bu NET'te değer eşdeğerlik uygulamak için en iyi yol -

1

iyi cevabı sınıf için IEquatable uygulamaktır.

Başka bir seçenek de sınıfın üyelerinin hepsi eşsiz bir karma bilgisayar ve ardından bu karşı değer karşılaştırmaları yapıyor olurdu, ama bu bir karşılaştırma işlevi yazma bile daha fazla iş;

+0

Karma yaklaşım, yanlış pozitiflere de yatkındır. – cdhowie

+0

Evet, gerçekten önermiyoruz. – Aaronontheweb

9

) için 'doğru' yolu NET'te bunu sizin sınıf için IEquatable arabirimini uygulamaktır: Ancak

public class SomeClass : IEquatable<SomeClass> 
{ 
    public string Name { get; set; } 
    public double Value { get; set; } 
    public int[] NumberList { get; set; } 

    public bool Equals(SomeClass other) 
    { 
     // whatever your custom equality logic is 
     return other.Name == Name && 
      other.Value == Value && 
      other.NumberList == NumberList; 
    } 
} 

, gerçekten, this isn't all you should do doğru yapmak istiyorum.Aynı zamanda, Eşittir (nesne, nesne) ve GetHashCode (object) yöntemlerini de geçersiz kılmalısınız, böylece çağrı kodunuz eşitliği (belki bir Sözlükde veya belki de biraz yazılan bir koleksiyonda), kodunuzu değil, bu nesnelerin benim tahminim nesneler için Eşittir yöntemini geçersiz zorunda kalacak olmasıdır olduğundan

public class SomeClass : IEquatable<SomeClass> 
{ 
    public string Name { get; set; } 
    public double Value { get; set; } 
    public int[] NumberList { get; set; } 

    /// <summary> 
    /// Explicitly implemented IEquatable method. 
    /// </summary> 
    public bool IEquatable<SomeClass>.Equals(SomeClass other) 
    { 
     return other.Name == Name && 
      other.Value == Value && 
      other.NumberList == NumberList; 
    } 

    public override bool Equals(object obj) 
    { 
     var other = obj as SomeClass; 
     if (other == null) 
      return false; 
     return ((IEquatable<SomeClass>)(this)).Equals(other); 
    } 

    public override int GetHashCode() 
    { 
     // Determine some consistent way of generating a hash code, such as... 
     return Name.GetHashCode()^Value.GetHashCode()^NumberList.GetHashCode(); 
    } 
} 
1

: tip eşitlik belirleyici faktör olacaktır. Aksi takdirde, Eşittir yöntemi, her iki nesnenin de aynı nesneyi ifade etmesi durumunda size verecektir.

Bu sorunun sizin için uygun olmadığını biliyorum. Ancak sınıfınızda az sayıda özellik bulunduğundan, yöntemi kolayca geçersiz kılabilirsiniz.

5

Bütün gün, farklı özelliklerle uğraşmak için çeşitli karmaşık bit mantığıyla bir nesnenin özelliklerini yansıtmaktan geçen bir uzatma yöntemini yazmakla harcadım ve gerçekten iyi duruma getirdikten sonra 16:55 de bana doğdu iki nesne seri takdirde, sadece Yani burada bile Sözlükler

public static class TExtensions 
    { 
     public static string Serialize<T>(this T thisT) 
     { 
      var serializer = new DataContractSerializer(thisT.GetType()); 
      using (var writer = new StringWriter()) 
      using (var stm = new XmlTextWriter(writer)) 
      { 
       serializer.WriteObject(stm, thisT); 
       return writer.ToString(); 
      } 
     } 
} 

üzerinde çalışan basit serileştirici uzatma yöntemi Şimdi test kadar basit olabilir olduğunu yaa ... iki dizeleri

gerek

Asset.AreEqual(objA.Serialise(), objB.Serialise()) 

Henüz kapsamlı bir test yapılmadı, ancak umut verici ve daha önemlisi, basit görünüyor. Her iki durumda da, yardımcı programınızda doğru bir şekilde kullanmak için kullanışlı bir yöntem var mı?

+0

Ancak, nesneniz dize özellikleri içeriyorsa, büyük/küçük harflerin karşılaştırmasını bozmaz mı? Yani, UnitedStates 'unitedStates' için eşit olmazdı. –

İlgili konular