2011-09-17 6 views
1

C#에서 LINQ를 사용하여 목록에서 고유 항목을 검색하고 싶습니다. 나는 카드의 명단 인 카드 카드를 가진 클래스 덱을 가지고있다. 또한, 클래스 카드는 스위트 룸 유형의 속성을 갖는다. 카드 목록에있는 모든 스위트 항목을 검색하지만 고유 한 스위트 만 검색하고 싶습니다. 내가 시도한 코드는 다음과 같습니다.LINQ를 사용하는 속성 별 고유 개체 C#

내가 실수하지 않는다면, 카드 목록에서 모든 고유 한 스위트를 가져와야합니다. 그러나 다음 테스트는 실패합니다.

// Creating test cards 
Card a = new Card(suite="spade", value="ace"); 
Card b = new Card(suite="spade", value="king"); 
List<Card> cards = new List<Card>(2) {a, b}; 

// Creating deck of cards 
Deck d = new Deck(cards); 

위의 코드는 같은 제품군으로 된 작은 카드 (2 장의 카드)를 만듭니다. 내가 얻고 것을 제외하고

d.Suites.Count == 1 

을 : 그래서, 다음 코드는 진정한 평가해야

d.Suites.Count == 2 

나는 몇 가지 코드를 ommitted,하지만 난 그게 관련이 있다고 생각하지 않습니다. 풀 데크 (예 : 52 장)로 코드를 실행하면 예상대로 4 개의 고유 한 스위트 룸을 갖게됩니다. 따라서 나는 꽤 당황 스럽다.

확장 메서드를 통해 문제를 해결했지만 LINQ를 통해 간단한 방법이 있는지 궁금합니다.

+0

어떻게'Deck.Suites'를 해결하기 위해'GetSuiteByCards()'를 호출합니까? 대부분 문제가있을 수 있습니다. – BrokenGlass

+0

'Deck.Suites' 속성의 코드는 무엇입니까? –

답변

3

클래스 카드

심령 디버깅 능력에 형 스위트 룸의 속성 스위트 룸이 있습니다. Suite이 참조 유형이고 Object.EqualsObject.GetHashCode을 덮어 쓰지 않았다고 추측합니다.

Suite의 경우 Object.EqualsObject.GetHashCode을 덮어 써야합니다. DistinctIEqualityComparer<Suite>의 구현을 제공하지 않을 경우 EqualityComparer<Suite>.Default을 사용합니다. EqualityComparer<Suite>.Default에 의해 반환 된 구현은 Object.EqualsObject.GetHashCode을 사용합니다. 그래서 이들을 오버라이드하지 않으면, 모델이 리턴 한 모델은 평등을 참조한다 (참조로 해시 코드).

또는 IEqualityComparer<Suite>을 구현하여 참조 평등이 아닌 비교를 수행하고 Enumerable.Distinct<TSource>(this IEnumerable<TSource>, IEqualityComparer<TSource>)에 인스턴스를 전달하십시오.

일부 코드는 생략했지만 적절하지 않다고 생각합니다. 풀 데크 (예 : 52 장)로 코드를 실행하면 예상대로 4 개의 고유 한 스위트 룸을 갖게됩니다. 따라서 나는 꽤 당황 스럽다.

관련성이 있지만 어떤 일이 벌어지고 있는지 추측 해 보겠습니다. 당신의 위의 코드에서 전체 목록은 아마 같은 것입니다 :

Card a = new Card(new Suite("spade"), new Value("ace")); 
Card b = new Card(new Suite("spade"), new Value("king")); 
List<Card> cards = new List<Card>(2) {a, b}; 

그래서 여기 당신은 Suite 대표 스페이드의 두 인스턴스를 만들 수 있습니다. 그러나이 두 인스턴스는 서로 다른 인스턴스이고 서로 Equals (및 필요에 따라 GetHashCode)을 재정의하지 않았기 때문에 동일하게 비교되지 않습니다.

List<Suite> suites = new List<Suite>() suites { 
    new Suite("spade"), 
    new Suite("heart"), 
    new Suite("club"), 
    new Suite("diamond") 
}; 

List<Value> values = new List<Value>() values { 
    new Value("ace"), 
    new Value("king"), 
    // etc. 
}; 

다음

var deck = from suite in suites 
      from value in values 
      select new Card(suite, value); 

이제 모든 카드가있는 공간을 나타냅니다

그러나, 52 카드 갑판의 경우는이 같은 짓을 내기 Suite과 동일한 참조를 공유하므로 Distinct은 괜찮습니다.

그런데 어쨌든 추천 유형으로 슈트와 값을 모델링하지 않습니다. 그것들은 정말로 가치 유형입니다. 심장은 심장이며, 그것은 그 정체성입니다. 정체성은 그것이 누구인가에 의해 정의되는 것이 아니라 그것이 무엇인지에 의해 정의됩니다.

값 형식에 대한 기본 항등 연산자가 값의 동일성이므로 전체 문제를 피할 수 있습니다.

+0

정보를 제공해 주셔서 감사합니다. Equals() 메서드와 GetHashCode() 메서드를 재정의하고 테스트합니다. –