使用linqc#通过属性实现唯一对象

本文关键字:实现 唯一 对象 属性 linqc# 使用 | 更新日期: 2023-09-27 18:09:06

我希望在c#中使用LINQ从列表中检索唯一项。我有一个类Deck,有一个属性Cards,它是Card的列表。此外,类Card有一个Suite类型的属性Suite。我想在卡的列表中检索所有的套房项目,但只有唯一的套房。我试过的代码是:

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张牌),具有相同的套件。因此,下面的代码应该求值为true:

d.Suites.Count == 1

除了我得到:

d.Suites.Count == 2

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

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

使用linqc#通过属性实现唯一对象

类Card有Suite类型的属性Suite

灵媒调试开启。我猜Suite是一个引用类型,你没有覆盖Object.EqualsObject.GetHashCode

您需要为Suite覆盖Object.EqualsObject.GetHashCode。如果不提供IEqualityComparer<Suite>的实现,则Distinct使用EqualityComparer<Suite>.DefaultEqualityComparer<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是可以的。

顺便说一下,我不会将suit和values建模为引用类型。它们确实是值类型。一颗心就是一颗心,这就是它的身份。它的身份不是由它是谁定义的,而是由它是什么来定义的。

这将从一开始就避免整个问题,因为值类型的默认相等操作符是值相等。