如何用LINQ Where条件过滤列表中的多键匹配元素?
问题原因分析
- a、b返回空列表:
Student是引用类型,默认情况下Contains方法比较的是对象的引用地址,而非属性值。list和query中的Student都是不同实例,所以Contains始终返回false。 - c返回4条数据:它的逻辑是判断
Id存在于query的Id集合且RelatedId存在于query的RelatedId集合,这会筛选出所有Id为1/2且RelatedId为1/2的对象,也就是list中的全部元素,不符合预期的匹配逻辑。
解决方案
方案1:让Student类支持值相等性
实现IEquatable<Student>接口,重写相等比较逻辑,让Contains按属性值判断相等:
class Student : IEquatable<Student> { public long Id { get; set; } public long RelatedId { get; set; } public bool Equals(Student other) { if (other is null) return false; return Id == other.Id && RelatedId == other.RelatedId; } public override bool Equals(object obj) => Equals(obj as Student); public override int GetHashCode() => HashCode.Combine(Id, RelatedId); }
修改后,直接使用你原来的a写法就能得到正确结果:
var result = list.Where(x => query.Contains(x)).ToList();
方案2:使用LINQ的Any方法直接比较属性
不修改Student类,通过Any检查query中是否存在属性完全匹配的对象:
var result = list.Where(student => query.Any(q => q.Id == student.Id && q.RelatedId == student.RelatedId) ).ToList();
方案3:借助匿名类型的默认值相等性
匿名类型的相等比较默认基于属性值,先将query转换为匿名类型的哈希集合,再进行匹配:
var queryAnon = query.Select(q => new { q.Id, q.RelatedId }).ToHashSet(); var result = list.Where(student => queryAnon.Contains(new { student.Id, student.RelatedId }) ).ToList();
内容的提问来源于stack exchange,提问作者Twoner
相关产品推荐
相关产品推荐

