2014-07-24 19 views
7

Listeden farklı bir nesneyi almak istiyorum. IEqualityComparer'ı ancak başarılı olmaksızın uygulamaya çalışıyorum. Birisi kodumu gözden geçirebilir ve IEqualityComparer hakkında biraz bilgi verebilirse lütfen. BuIEqualityComparer Uygulamasını Uygula

public class Message 
{ 
    public int x { get; set; } 
    public string y { get; set; } 
    public string z { get; set; } 
    public string w { get; set; } 
} 

public class MessageComparer : IEqualityComparer<Message> 
{ 
    public bool Equals(Message x, Message y) 
    { 
     if (Object.ReferenceEquals(x, y)) return true; 

     if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null)) 
      return false; 
     if (x.x == y.x && x.y == y.y && x.z == y.z && x.w == y.w) 
     { 
      return true; 
     } 
     return false; 
    } 

    public int GetHashCode(Message number) 
    { 
     //if (Object.ReferenceEquals(number, null)) return 0; 
     int hashX = number.x.GetHashCode(); 
     int hashY = number.y == null ? 0 : number.y.GetHashCode(); 
     int hashZ = number.z == null ? 0 : number.z.GetHashCode(); 
     int hashW = number.w == null ? 0 : number.w.GetHashCode(); 

     return hashX^hashY^hashZ^hashW; 

    } 
} 

Mesaj ile benim liste nesneleri:

Message m1 = new Message(); 
     m1.x = 1; 
     m1.y = "A"; 
     m1.z = "B"; 
     m1.w = "C"; 

     Message m2 = new Message(); 
     m2.x = 1; 
     m2.y = "A"; 
     m2.z = "B"; 
     m2.w = "C"; 

     Message m3 = new Message(); 
     m3.x = 1; 
     m3.y = "A"; 
     m3.z = "B"; 
     m3.w = "C"; 

     Message m4 = new Message(); 
     m4.x = 2; 
     m4.y = "A"; 
     m4.z = "B"; 
     m4.w = "C"; 

     Message m5 = new Message(); 
     m5.x = 3; 
     m5.y = "W"; 
     m5.z = "D"; 
     m5.w = "C"; 

     Message m6 = new Message(); 
     m6.x = 4; 
     m6.y = "S"; 
     m6.z = "F"; 
     m6.w = "R"; 

     List<Message> collection = new List<Message>(); 
     collection.Add(m1); 
     collection.Add(m2); 
     collection.Add(m3); 
     collection.Add(m4); 
     collection.Add(m5); 

     collection.Distinct(new MessageComparer()); 

ben listedeki elemanların Farklı() yöntemi numarasını aramak

aynıdır Ben şu durum var. Teşekkür ederiz.

+1

bir değişkene ayrı çağrısının sonucunu atama ya da sadece orijinal listeyi sorguluyor musunuz fazla detay bilgi için bu bağlantıyı bakın? Bir şeye atama yapmıyorsanız, yapmanız gerekir. 'Distinct()' yerine bir IEnumerable 'yerine bir güncelleme yapıyor – eouw0o83hf

+0

Teşekkürler, haklısınız :) – kat1330

cevap

11

bu deneyin:

var distinct = collection.Distinct(new MessageComparer()); 

Sonra bundan sonra herhangi bir şey için distinct kullanın.

IEnumerable<>'un değişmez yapısını unutuyor gibi görünüyor. LINQ yöntemlerinden hiçbiri orijinal değişkeni değiştirmez. Bunun yerine, ifadenin sonucunu içeren IEnuerable<T> s döndürürler. Örneğin, içeriğini { "a", "a", "b", "c" } içeriğiyle birlikte düşünelim.

Şimdi original.Add("d"); numaralı telefonu arayalım. Bu yöntemin dönüş değeri yoktur (void). Ancak, daha sonra original içeriğini yazdırırsak, { "a", "a", "b", "c", "d" }'u göreceğiz. Diğer yandan, şimdi original.Skip(1) numaralı telefonu arayabiliriz. Bu yöntem yapar, IEnumerable<string> türünde bir dönüş değeri vardır. Bu bir LINQ ifadesidir ve orijinal koleksiyonda hiçbir yan etki gerçekleştirmez. Bu nedenle, buna original numaralı telefondan bakarsak, { "a", "a", "b", "c", "d" }'u göreceğiz. Ancak, yöntemden sonuç { "a", "b", "c", "d" } olacaktır. Gördüğünüz gibi, sonuç bir elemanı atlar.

Bunun nedeni LINQ yöntemlerinin parametre olarak IEnumerable<T> kabul etmeleridir. Sonuç olarak, orijinal listenin uygulanmasına dair hiçbir fikri yoktur. Uzatma yöntemi ile bir ReadOnlyCollection'u geçiyor olabilirsiniz ve yine de bunları değerlendirebilirler. Daha sonra orijinal koleksiyonu değiştiremezler çünkü orijinal koleksiyon herhangi bir şekilde yazılabilir.

Hepsi bu, ancak tablo halinde. Her satır orijinal { "a", "a", "b", "c" } başlar:

Context  Example function Immutable? Returned Value  Collection after calling 
Collection Add("d")   No   (void)    { "a", "a", "b", "c", "d" }: 
LINQ  Skip(1)    Yes   { "a", "b", "c" } { "a, "a", "b", "c" }: 
2

Sen IEqualityComparer uygulamak gerekmez:

public class Message 
    { 
     protected bool Equals(Message other) 
     { 
      return string.Equals(x, other.x) && string.Equals(y, other.y) && string.Equals(z, other.z) && string.Equals(w, other.w); 
     } 

     public override bool Equals(object obj) 
     { 
      if (ReferenceEquals(null, obj)) return false; 
      if (ReferenceEquals(this, obj)) return true; 
      if (obj.GetType() != this.GetType()) return false; 
      return Equals((Message) obj); 
     } 

     public override int GetHashCode() 
     { 
      unchecked //Ignores overflows that can (should) occur 
      { 
       var hashCode = x; 
       hashCode = (hashCode*397)^(y != null ? y.GetHashCode() : 0); 
       hashCode = (hashCode*397)^(z != null ? z.GetHashCode() : 0); 
       hashCode = (hashCode*397)^(w != null ? w.GetHashCode() : 0); 
       return hashCode; 
      } 
     } 

     public int x { get; set; } 
     public string y { get; set; } 
     public string z { get; set; } 
     public string w { get; set; } 
    } 
+0

Davaya bağlı. Bu tür bir karşılaştırmanın sadece belirli bir ayrı durumda olması gerekiyorsa, ayrı bir karşılaştırıcı kullanmak daha iyidir. Override Eşitleme yöntemi de başka yerleri de etkiler. –

+0

Diğer yerleri olumlu yönde etkiler, genellikle böyle bir veri sınıfı için uygulamak istersiniz. –

0

http://dotnetvisio.blogspot.in/2015/12/usage-of-icomparer-icomparable-and.html

IEqualityComparer bir daha detay bilgi için bu bağlantıyı bakın Eşit olup olmadığını nesneyi bulmak için kullanılan arayüz, Şimdi bunu bulmamız gereken bir örnekte göreceğiz Bir koleksiyondaki bir nesnenin farklılığı.Bu arayüz bir yöntemini Eşittir (T obj1 T obj2) uygulayacak

soyut public class Kişi { kamu dize Ad {get; set; } public string LastName {get; set; } genel dize Adres {set; almak; } }

public enum SortType 
{ 
    ByID, 
    BySalary 
} 

    public class EmployeeDistinctEquality : IEqualityComparer<Employee> 
    { 
     public EmployeeDistinctEquality() 
     { 

     } 

     public bool Equals(Employee x, Employee y) 
     { 
      if (x == null && x == null) 
       return true; 
      else if (x == null || y == null) 
       return false; 
      else if (x.Id == y.Id) 
       return true; 
      else 
       return false; 
     } 

     public int GetHashCode(Employee obj) 
     { 
      return obj.Id.GetHashCode(); 
     } 
    } 

http://dotnetvisio.blogspot.in/2015/12/usage-of-icomparer-icomparable-and.html