C# - 具有接口类型列表的相等运算符未按预期工作

C# - equality operator with list of interface type not working as expected

考虑以下代码,其中 ClassOne 是从 IClass 派生的 class:

List<IClass> list = new List<IClass>();
list.Add(new ClassOne("foo", "bar"));
list.Add(new ClassOne("baz", "bam"));

List<IClass> list2 = new List<IClass>();
list2.Add(new ClassOne("foo", "bar"));
list2.Add(new ClassOne("baz", "bam"));

if (list == list2)
    Console.WriteLine("Lists are equal.");
else
    Console.WriteLine("Lists are NOT equal.");

相等运算符 return 为假(即列表不匹配),除此之外 operator ==operator !=Equals(ClassOne)Equals(object)GetHashCode() 已经 implemented/overridden ClassOne。这是为什么?我希望相等运算符 return 为真。是否有任何其他 methods/interfaces 必须实施才能使 == 运算符按预期工作?

作为参考,这里是 ClassOneIClass 的实现:

public interface IClass
{
    string getA();
    string getB();
} //interface


public class ClassOne : IClass, IEquatable<ClassOne>
{
    public ClassOne(string a, string b)
    {
        strA = a;
        strB = b;
    }

    public string getA()
    {
        return strA;
    }

    public string getB()
    {
        return strB;
    }

    public bool Equals(ClassOne other)
    {
        if (ReferenceEquals(null, other)) return false;
        if (ReferenceEquals(this, other)) return true;
        if (!string.Equals(strA, other.strA))
            return false;
        return string.Equals(strB, other.strB);
    }

    public override bool Equals(object other)
    {
        if (ReferenceEquals(null, other)) return false;
        if (ReferenceEquals(this, other)) return true;
        if (other is ClassOne)
        {
            ClassOne c1 = (ClassOne)other;
            return Equals(c1);
        }
        //not ClassOne, so it is not equal
        return false;
    }

    public override int GetHashCode()
    {
        int hc_a = -1;
        if (null != strA)
            hc_a = strA.GetHashCode();
        int hc_b = -1;
        if (null != strB)
            hc_b = strB.GetHashCode();
        return hc_a ^ hc_b;
    }

    public static bool operator ==(ClassOne left, ClassOne right)
    {
        if (ReferenceEquals(left, right)) return true;
        if (ReferenceEquals(left, null) || ReferenceEquals(right, null))
            return false;
        return left.Equals(right);
    }

    public static bool operator !=(ClassOne left, ClassOne right)
    {
        return !(left == right);
    }

    private string strA, strB;
} //class

任何正确方向的帮助或提示都将不胜感激。谢谢。

Why is that? I would expect the equality operator to return true.

不正确 - == 运算符(和 Equals())未在 List<T> 上定义以检查其内容的相等性 - 它默认引用定义在上的运算符的相等性object。由于两个列表是不同的对象,== returns false.

您可以使用 Linq SequenceEqual 方法来确定两个列表是否包含相同顺序的相同对象:

if (list.SequenceEqual(list2))
    Console.WriteLine("Lists are equal.");
else
    Console.WriteLine("Lists are NOT equal.");

因为 == 运算符没有为 List<T> class 重载。 == 对于列表来说只是引用相等。即使两个 List<int> 持有相同 int 的对象也不相等,等等

如果你问是否list == list2,编译器会为List<T>调用==运算符,而List<T>class的设计者已经决定了只有当两个列表都引用同一个列表时,两个列表才相等。换句话说:

public class List<T> {

    public static bool operator ==(List<T> left, List<T> right) {
        return ReferenceEquals(left, right);
    }

}

(可见List<T>class的内容比较多,而且由于使用了引用相等,所以not要重载运算符) .