2011-11-29 17 views
10

Mam dwie listy patrz niżej ..... wynik wraca jako pustyPrzecięcie między dwie listy nie działa

List<Pay>olist = new List<Pay>(); 
List<Pay> nlist = new List<Pay>(); 
Pay oldpay = new Pay() 
{ 
    EventId = 1, 
    Number = 123,       
    Amount = 1 
}; 

olist.Add(oldpay); 
Pay newpay = new Pay() 
{ 
    EventId = 1, 
    Number = 123,       
    Amount = 100 
}; 
nlist.Add(newpay); 
var Result = nlist.Intersect(olist); 

każdy trop, dlaczego?

+0

Zakładając równość Pay jest identyfikatorem zdarzenia, numerem i kwotą, nie ma nic wspólnego na tych dwóch listach i dlatego nic nie przecina. Innymi słowy, nie zdefiniowałeś tutaj równości. –

+0

Co masz na myśli, że nie zdefiniowałeś tutaj równości? tylko inny element to Kwota = 100 – user570715

+0

Nie ma nic w pytaniu, w którym stany _why_ 'oldpay' powinny być równe' newpay'. –

Odpowiedz

21

Trzeba zastąpić metody Equals i GetHashCode w swojej klasie Pay, inaczej Intersect nie wie, kiedy 2 przypadki są uważane za równe. Jak można się domyślić, że jest to EventId, który określa równość? oldPay i newPay są różnymi instancjami, więc domyślnie nie są uznawane za równe.

Można zastąpić metody w Pay tak:

public override int GetHashCode() 
{ 
    return this.EventId; 
} 

public override bool Equals(object other) 
{ 
    if (other is Pay) 
     return ((Pay)other).EventId == this.EventId; 
    return false; 
} 

Inną opcją jest wdrożenie IEqualityComparer<Pay> i przekazać go jako parametr do Intersect:

public class PayComparer : IEqualityComparer<Pay> 
{ 
    public bool Equals(Pay x, Pay y) 
    { 
     if (x == y) // same instance or both null 
      return true; 
     if (x == null || y == null) // either one is null but not both 
      return false; 

     return x.EventId == y.EventId; 
    } 


    public int GetHashCode(Pay pay) 
    { 
     return pay != null ? pay.EventId : 0; 
    } 
} 

... 

var Result = nlist.Intersect(olist, new PayComparer()); 
+2

lub możesz napisać własnego porównywalnika: http://msdn.microsoft.com/en-us/library/234b841s.aspx – mydogisbox

+0

@mydogisbox, tak, faktycznie edytowałem swoją odpowiedź, aby o tym wspomnieć, gdy skomentowałeś;) –

+0

Lub możesz uczynić typ 'Pay'' struct', który ma to dla ciebie, chociaż domyślna implementacja jest wolna, ponieważ używa refleksji. – Gebb

0

Intersect jest prawdopodobnie tylko dodawania obiektów gdy to samo wystąpienie Pay jest w obu List. Jako oldPay i newPay są tworzone oddzielnie, są uważane za nie równe.

Intersect używa metody Equals do porównywania obiektów. Jeśli go nie zastąpisz, zachowuje to samo zachowanie klasy Object: zwracając true tylko wtedy, gdy obie są tą samą instancją obiektu.

Należy zastąpić metodę Equals w Pay.

//in the Pay class 
    public override bool Equals(Object o) { 
     Pay pay = o as Pay; 
     if (pay == null) return false; 
     // you haven't said if Number should be included in the comparation 
     return EventId == pay.EventId; // && Number == pay.Number; (if applies) 
    } 
0

Obiekty są typami odniesienia. Kiedy tworzysz dwa obiekty, masz dwa unikalne odniesienia. Jedynym sposobem, w jaki kiedykolwiek będą one porównywane, jest:

object a = new object(); 
object b = a; 

W tym przypadku (a == b) jest prawdziwe. Czytaj na temat typów reference vs value i objects

Aby naprawić problem, należy zastąpić Equals i GetHashCode, jak wskazał Thomas Levesque.