












在 C# LINQ 中,Concat、Union、Intersect、Except 是处理集合合并/筛选的核心方法,覆盖拼接、去重合并、交集、差集四大核心场景。结合你提供的宠物(pets)/宠物主人(people)代码示例,以下是清晰的对比、用法和实操演示:
先明确每个方法的核心行为,以及相等性比较在其中的角色:
| 方法 | 核心作用 | 是否依赖“相等性比较” | 核心特点 |
|---|---|---|---|
Concat |
拼接两个集合(A + B),保留所有元素 | ❌ 不依赖 | 简单拼接,重复元素会保留 |
Union |
合并两个集合并去重(A ∪ B) | ✅ 依赖 | 合并后仅保留唯一元素 |
Intersect |
取两个集合的交集(同时存在于A和B的元素) | ✅ 依赖 | 只保留“共有元素” |
Except |
取两个集合的差集(A有、B没有的元素) | ✅ 依赖 | 只保留“A独有的元素” |
基于你提供的 pets(8只宠物)和 people(关联前6只),结合默认比较和自定义 IEqualityComparer<T> 演示:
var cats = pets.Where(p => p.Type == PetType.Cat); // ID:2、3、7、8
var dogs = pets.Where(p => p.Type == PetType.Dog); // ID:4、5、6
var concatResult = cats.Concat(dogs);
// 结果:2、3、7、8、4、5、6(共7个元素,无去重)
行为:合并A和B,自动去重(判定“重复”的核心是相等性比较)。
相等性规则的影响:
Pet 自身的 IEquatable<T> 或引用地址;IEqualityComparer<T> 指定规则。示例:
// 被主人关联的猫(ID:2、3)
var ownedCats = people.SelectMany(p => p.Pets).Where(p => p.Type == PetType.Cat);
// 所有猫(ID:2、3、7、8)
var allCats = pets.Where(p => p.Type == PetType.Cat);
// ① 默认比较(按Pet的IEquatable<T>,这里是按ID)
var unionDefault = ownedCats.Union(allCats);
// 结果:2、3、7、8(去重,保留唯一ID)
// ② 自定义比较器(按“宠物名称”去重)
var unionWithComparer = ownedCats.Union(allCats, new PetNameEqualityComparer());
// 结果:按名称去重(若有名称重复的猫,仅保留一个)
var allCats = pets.Where(p => p.Type == PetType.Cat); // 所有猫
var ownedPets = people.SelectMany(p => p.Pets); // 被主人关联的宠物
// ① 默认比较(按ID)
var intersectDefault = allCats.Intersect(ownedPets);
// 结果:ID=2、3的猫(这两只猫同时在“所有猫”和“被关联宠物”中)
// ② 自定义比较器(按“类型+重量”)
var intersectWithComparer = allCats.Intersect(ownedPets, new PetTypeWeightComparer());
// 结果:类型为Cat、且重量与被关联宠物一致的元素
var allCats = pets.Where(p => p.Type == PetType.Cat); // 所有猫
var ownedPets = people.SelectMany(p => p.Pets); // 被主人关联的宠物
// ① 默认比较(按ID)
var exceptDefault = allCats.Except(ownedPets);
// 结果:ID=7、8的猫(这两只猫在“所有猫”中,但不在“被关联宠物”中)
// ② 自定义比较器(按“名称”)
var exceptWithComparer = allCats.Except(ownedPets, new PetNameEqualityComparer());
// 结果:名称不在“被关联宠物”中的猫
Union/Intersect/Except 的行为完全由相等性规则决定,而规则的选择分两种场景:
| 场景 | 实现方式 | 适用情况 |
|---|---|---|
| 默认比较 | 实体类实现 IEquatable<T>,或重写 Equals/GetHashCode |
规则固定、可修改实体类源码 |
| 自定义比较 | 实现 IEqualityComparer<T>,传入LINQ方法重载 |
规则灵活、不可修改实体类、多规则切换 |
Concat:拼集合,不查重,无比较;Union:合并后去重,相等则去重;Intersect:找共有,相等才保留;Except:找独有,A有B无(相等则排除);IEquatable<T> 或 IEqualityComparer<T> 决定,后者更灵活。此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。