2011-09-17 29 views
1

我希望从列表中检索使用LINQ在C#中的唯一项目。 我有一个类甲板,与属性卡是卡的名单。此外,班卡有一个套房类型套房。我想检索卡片列表中的所有套件物品,但只能检索独特的套件。我试过的代码是:按属性使用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 

我已经ommitted一些代码,但我不认为这是相关的。如果我使用全套牌(即52张牌)运行代码,我会得到4套独特套件,如预期的那样;因此我很困惑。

我已经通过扩展方法解决了这个问题,但我想知道是否有一种简单的方法可以通过LINQ来实现。

+0

如何调用'GetSuiteByCards()'来解析'Deck.Suites'?最可能的问题是 – BrokenGlass

+0

属性'Deck.Suites'的代码是什么? –

回答

3

类卡有

心理调试权力上型套件的性能套件。我猜Suite是一个参考类型,你没有覆盖Object.EqualsObject.GetHashCode

对于Suite,您需要覆盖Object.EqualsObject.GetHashCodeDistinct使用EqualityComparer<Suite>.Default如果您未提供IEqualityComparer<Suite>的实施。由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)。

然而,在52张牌的情况下,我敢打赌,你做了这样的事情:

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); 

现在所有的卡片代表一个空间是与Suite共享相同的参考,因此Distinct没问题。

顺便说一句,我不会将适合和值作为参考类型。他们确实是价值类型。心是一颗心,那就是它的身份。它的身份不是由谁定义的,而是由它的内容决定的。

无论如何,这将避免整个问题开始,因为值类型的默认相等运算符是值相等。

+0

感谢您的信息。我将重写Equals()方法,以及GetHashCode()方法和测试。 –