具有相同元素的两个列表不相等.为什么
本文关键字:两个 列表 为什么 不相等 元素 | 更新日期: 2023-09-27 17:53:47
我有以下内容:
var a = new List<OrderRule> {
new OrderRule("name", OrderDirection.Ascending),
new OrderRule("age", OrderDirection.Descending)
};
var b = new List<OrderRule> {
new OrderRule("name", OrderDirection.Ascending),
new OrderRule("age", OrderDirection.Descending)
};
var r = a.Equals(b);
变量r为假,即使两个列表包含彼此相等的项。OrdeRule类实现了等价质量。注意,当Direction和Property都相等时,两个OrderRules是相等的。
public enum OrderDirection { ASC, DESC }
public class OrderRule : IEquatable<OrderRule> {
public OrderDirection Direction { get; }
public String Property { get; }
public OrderRule(String property, OrderDirection direction) {
Direction = direction;
Property = property;
}
public Boolean Equals(OrderRule other) {
if (other == null)
return false;
return Property.Equals(other.Property) && Direction.Equals(other.Direction);
}
public override Boolean Equals(Object obj) {
if (ReferenceEquals(null, obj))
return false;
if (ReferenceEquals(this, obj))
return true;
if (obj.GetType() != GetType())
return false;
return Equals(obj as IncludeRule);
}
public override Int32 GetHashCode() {
return HashCode.Of(Property).And(Direction);
}
}
我错过了什么?
检查两个列表是否相等并不意味着检查它们是否包含相同的项。
如果你这样做:
var a = new List<OrderRule>();
var b = new List<OrderRule>();
var r = a.Equals(b); //false
r
将始终为假,即使两个列表中有相同的项。那是因为你没有检查列表的内容。你实际上是在检查a
和b
是否指向同一个对象。但a
是一个对象,b
是另一个对象。
如果你这样做,r
将为真:
var a = new List<OrderRule>();
var b = a;
var r = a.Equals(b) //true
如果你有两个列表,你想看看它们是否以相同的顺序包含相同的项,你可以这样做:
var r = a.SequenceEquals(b);
在问题中的示例中,r
将是true
,因为您在OrderRule
上重写了Equals
,因此一个列表中的项目被认为与另一个列表中的项目"相等"。
知道了-你在OrderRule
中的平等检查被打破了。
public override Boolean Equals(Object obj) {
if (ReferenceEquals(null, obj))
return false;
if (ReferenceEquals(this, obj))
return true;
if (obj.GetType() != GetType())
return false;
return Equals(obj as IncludeRule);
}
我想你应该是指return Equals(obj as OrderRule)
,而不是return Equals(obj as IncludeRule)
。
您的代码正在测试它们是否相同的列表。如果它们有相同的内容就不会。
a.Equals(b); // false
var d = a;
d.Equals(a); // true
如果你想比较内容,那么使用linq的SequenceEqual
https://msdn.microsoft.com/en-us/library/bb348567 (v = vs.100) . aspx
首先,无论何时使用new
关键字或创建新对象,对象的引用或地址都存储在变量中。还可以比较变量的值。
现在您已经覆盖了OrderRule
的equals函数。因此,如果你在两个OrderRule
上做等号运算,你会得到结果,因为你在重写的等号函数中比较它。
但是现在想想这个什么是List<OrderRule>
它只是一个泛型类。同样,等号会检查包含引用的变量的值,因为它们是不同的,当你比较它们时,你不会得到真值。另外,List实现了与未被覆盖的对象相同的等号。因此,我更喜欢的一种方法是创建一个扩展。
public static class Extensions
{
public static bool Equal<T>(this List<T> x, List<T> y)
{
bool isEqual = true;
if (x == null ^ y == null)
{
isEqual = false;
}
else if (x == null && y == null)
{
isEqual = true;
}
else if (x.Equals(y))
{
isEqual = true;
}
else if (x.Count != y.Count)
{
isEqual = false;
}
else
{
//This logic can be changed as per your need.
//Here order of the list matters!
//You can make one where order doesn't matter
for (int i = 0; i < x.Count; i++)
{
if (!x[i].Equals(y[i]))
{
break;
}
}
}
return isEqual;
}
}
这样做是比较引用而不是对象。所以你得到不等式返回