具有相同元素的两个列表不相等.为什么

本文关键字:两个 列表 为什么 不相等 元素 | 更新日期: 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将始终为假,即使两个列表中有相同的项。那是因为你没有检查列表的内容。你实际上是在检查ab是否指向同一个对象。但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;
    }
}

这样做是比较引用而不是对象。所以你得到不等式返回