如何检查列表中所有对象的属性是否全部相等?
为什么你的Lambda表达式返回false?以及正确的实现方法
嘿,我来帮你搞明白这个问题~
你遇到的问题核心在于:对于自定义的引用类型(比如你写的Person类),默认的==运算符比较的是对象的内存引用地址,而不是属性值。哪怕两个Person对象的Id和Name完全一样,它们也是内存里的两个不同实例,所以o == persons.First()会返回false。
接下来给你几种正确的实现方式,你可以根据自己的场景选择:
方法1:重写Person类的Equals和GetHashCode(最规范的做法)
如果Person是你自己定义的类,推荐直接重写这两个方法,让类自己定义“相等”的逻辑:
public class Person { public string Id { get; set; } public string Name { get; set; } // 重写Equals方法,按属性比较 public override bool Equals(object obj) { // 如果obj不是Person类型,直接返回false if (obj is not Person otherPerson) return false; // 比较所有需要判断相等的属性 return Id == otherPerson.Id && Name == otherPerson.Name; } // 必须同时重写GetHashCode,保证相等的对象哈希码一致 public override int GetHashCode() { return HashCode.Combine(Id, Name); } }
修改之后,你原来的代码var areEqual = persons.All(o => o == persons.First());就会返回true了,也可以用o.Equals(persons.First()),效果是一样的。
方法2:直接在Lambda里逐一比较属性(无需修改Person类)
如果不能修改Person类的代码,或者只是临时需要判断相等,可以直接在All方法里指定属性比较逻辑:
var firstPerson = persons.First(); var areEqual = persons.All(o => o.Id == firstPerson.Id && o.Name == firstPerson.Name );
这种方式简单直接,适合属性不多的场景。
方法3:用值元组简化属性比较(.NET Core/.NET 5+可用)
如果你的项目用的是较新的.NET版本,可以用值元组来快速打包属性,简化比较代码:
var firstPerson = persons.First(); var areEqual = persons.All(o => (o.Id, o.Name) == (firstPerson.Id, firstPerson.Name) );
值元组的==会自动逐一比较内部元素,代码看起来更简洁。
方法4:用record类型代替class(.NET 6+可用)
如果你用的是.NET 6及以上版本,可以把Person定义为record类型,record默认就是按属性值来判断相等的:
public record Person(string Id, string Name);
这样定义后,你原来的代码var areEqual = persons.All(o => o == persons.First());直接就能返回true,完全不用额外重写方法,非常方便。
内容的提问来源于stack exchange,提问作者Aԃιƚყα Gυɾαʋ
相关产品推荐
相关产品推荐

