使用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来做到这一点。
类Card有Suite类型的属性Suite
灵媒调试开启。我猜Suite
是一个引用类型,你没有覆盖Object.Equals
和Object.GetHashCode
。
您需要为Suite
覆盖Object.Equals
和Object.GetHashCode
。如果不提供IEqualityComparer<Suite>
的实现,则Distinct
使用EqualityComparer<Suite>.Default
。EqualityComparer<Suite>.Default
返回的实现使用Object.Equals
和Object.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
是可以的。
这将从一开始就避免整个问题,因为值类型的默认相等操作符是值相等。