2011-09-17 2 views
1

C#でLINQを使用してリストから一意のアイテムを取得したいとします。 私はクラスのデッキを持っていて、カードのリストであるプロパティのカードを持っています。さらに、クラスのカードはSuite Suiteのスイートスイートを所有しています。私は、カードのリストにあるすべてのスイートアイテムを検索したいが、ユニークなスイートのみを検索したい。私が試したコードは次のとおりです:LINQを使用するプロパティによる一意のオブジェクトC#

List<Suite> GetSuiteByCards(List<Card> cards) 
    { 
     List<Suite> list = cards.Select(c => c.Suite).Distinct().ToList(); 
     return list; 
    } 

私が間違っていない場合、これはカードのリストからすべてのユニークなスイートを取得する必要があります。ただし、次のテストは失敗します。

// 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 

私はいくつかのコードを省略されているが、私はそれが関連しているとは思いません。フルデッキ(コード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表すスペードの2つのインスタンスを作成しています。ただし、これらの2つのインスタンスは異なるインスタンスであり、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()メソッドをオーバーライドしてテストします。 –

関連する問題