2010-08-06 2 views
2

은 내가 나던 다음 코드는 제대로 동작했다 :왜 .Except() 및 Intersect() LINQ를 사용하여 여기에서 작동하지 않습니다?

컨텍스트 : 내가 두 개체 목록이 있습니다
* listOne가 100 개 개의 레코드를
* listTwo 70 개 기록

많은있다 그것들은 (두 목록 모두에서) 동일한 Id 속성을가집니다. 이 코드를 실행하고 (30 있어야한다)는 여전히 100 개 개의 레코드가있는 결과

listOneOnlyItems 

조사 후

var listOneOnlyItems = listOne.Except(listTwo, new ItemComparer()); 

여기에 비교 자

public class ItemComparer : IEqualityComparer<Item> 
{ 
    public bool Equals(Item x, Item y) 
    { 
     if (x.Id == y.Id) 
      return true; 

     return false; 
    } 

    public int GetHashCode(Item obj) 
    { 
     return obj.GetHashCode(); 
    } 
} 

입니다. 누구든지 나를 도울 수 있습니까?

IEnumerable<Item> sharedItems = listOne.Intersect(listTwo, new ItemComparer()); 

수익을 실행 또한

+2

"return (x.Id == y.Id)"이라고 입력하면됩니다. – Gelatin

+0

@ Simon Brown - 감사하지만 질문에 대한 답변에 도움이되지 않습니다. – leora

+0

"Item"은 Id 이외의 것을 사용하여 GetHashCode를 구현합니까? –

답변

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

가치 수표를 반환 - IIRC GetHashCode()는 동등하기 전에 먼저 테스트되며, 동일한 해시가없는 경우 평등을 검사하지 않아도됩니다. obj.GetHashCode()에서 무엇을 기대할 지 잘 모르겠습니다. Item 클래스에서 구현 한 기능에 따라 다릅니다.

+1

신속하고 지저분한 콘솔 앱에서이를 확인했습니다. – kbrimington

+0

이상한,이 Except() 고정하지만 intersect() 여전히 0 항목을 보여줍니다. . 이견있는 사람? – leora

+0

흥미 롭습니다 - MSDN을 통해 읽는 중, '인터셉트'(Except)가 지연 실행을 사용하는 것으로 보입니다 -이 문제를 볼 수 있습니까? '.ToList()'를 호출하면 데이터가 강제적으로 실현되어야한다. 그것 이외에, 나는 (입력 오 류를 확인하는 것 말고는) 난처한 상황이다. 두 비교 자 모두 동일해야하며 둘 다 같은 방식으로 호출해야합니다 (지연 실행 경고가있는 경우) – PeterL

0

하게 고려 sharedItems 컬렉션에서 reesults을 제로 GetHashCode() 이상 obj.Id.GetHashCode()

0

이 코드는 잘 작동 :

static void TestLinqExcept() 
{ 
    var seqA = Enumerable.Range(1, 10); 
    var seqB = Enumerable.Range(1, 7); 
    var seqAexceptB = seqA.Except(seqB, new IntComparer()); 
    foreach (var x in seqAexceptB) 
    { 
     Console.WriteLine(x); 
    } 
} 

class IntComparer: EqualityComparer<int> 
{ 
    public override bool Equals(int x, int y) 
    { 
     return x == y; 
    } 

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

당신은 당신의 EqualityComparer 방법으로 '재정의'키워드를 추가해야합니다. (암시 적으로 C# 디자이너 측에서는 실수 였기 때문에 '무시'하지 않는 것이 좋다고 생각합니다.)

+0

실례합니다. IEqualityComparer를 구현하는 것을 보았습니다. 글쎄, 그것은 잘 작동하는 내 테스트 코드를 쉽게 변경할 수 있습니다. GetHashCode *는 두 항목을 비교할 때마다 호출됩니다. – Rafe

+0

그런데 IEqualityComparer가 필요없는 seqA.Where (a =>! seqB.Contains (a))를 사용하는 것이 좋습니다. 또는 더 좋게는 SortedSet과 같은 것을 사용하십시오. – Rafe

관련 문제