EqualityComparerer 。Default.Equals()与object.Equals()和多态性

问题描述 投票:2回答:2

再次讨论平等时,我偶然发现了EqualityComparer<T>.Default.Equals()。我更喜欢为引用类型而不是object.Equals()调用此方法。现在我认为我错了。

[object.Equals()使用可重写的实例Equals()方法提供正确的多态行为,而EqualityComparer<T>.Default.Equals()如果实现则调用IEquatable<T>.Equals()

现在考虑这个小程序:

public class Class1 : IEquatable<Class1>
{
    public int Prop1 { get; set; }

    public bool Equals(Class1 other)
    {
        if (other == null)
            return false;

        return Prop1 == other.Prop1;
    }

    public override bool Equals(object obj)
    {
        if (obj == null || GetType() != obj.GetType())
        {
            return false;
        }

        return Equals(obj as Class1);
    }
}

public class Class2 : Class1, IEquatable<Class2>
{
    public int Prop1 { get; set; }
    public int Prop2 { get; set; }

    public bool Equals(Class2 other)
    {
        if (other == null)
            return false;

        return Prop1 == other.Prop1 && Prop2 == other.Prop2;
    }

    public override bool Equals(object obj)
    {
        if (obj == null || GetType() != obj.GetType())
        {
            return false;
        }

        return Equals(obj as Class2);
    }
}


class Program
{
    static void Main(string[] args)
    {
        var c1 = new Class1 {Prop1 = 10};
        var c2 = new Class2 {Prop1 = 10, Prop2 = 5};
        var c3 = new Class2 {Prop1 = 10, Prop2 = 15};

        Console.WriteLine("Object.Equals()");
        Console.WriteLine("C1=C2 {0}",Equals(c1,c2));
        Console.WriteLine("C2=C1 {0}",Equals(c2, c1));
        Console.WriteLine("C2=C3 {0}",Equals(c2, c3));
        Console.WriteLine("C3=C2 {0}", Equals(c3, c2));

        var dec1 = EqualityComparer<Class1>.Default;

        Console.WriteLine();
        Console.WriteLine("EqualityComparer<Class1>.Default.Equals");
        Console.WriteLine("C1=C2 {0}", dec1.Equals(c1, c2));
        Console.WriteLine("C2=C1 {0}", dec1.Equals(c2, c1));
        Console.WriteLine("C2=C3 {0} BUG?", dec1.Equals(c2, c3));
        Console.WriteLine("C3=C2 {0} BUG?", dec1.Equals(c3, c2));

        Console.ReadKey();
    }
}

它显示出在相等语义上带来不一致是多么容易:

Object.Equals()C1 = C2错误C2 = C1错误C2 = C3错误C3 = C2错误EqualityComparer .Default.EqualsC1 = C2错误C2 = C1错误C2 = C3真错误?C3 = C2真错误?

但是MSDN Documentation建议:

实施者注意事项如果您实施Equals,还应该重写Object.Equals(Object)的基类实现,并重写GetHashCode,以便其行为与IEquatable 。等于方法。如果您确实重写Object.Equals(Object),您覆盖的实现也会在对static的调用中调用类上的Equals(System.Object,System.Object)方法。在另外,您应该重载op_Equality和op_Inequality操作员。这样可确保所有相等性测试返回一致结果,如示例所示。

从这一刻起,我认为没有理由为引用类型实现IEquatable<T>。谁能告诉我什么时候有意义?当我们以不同的方式看待类型(作为基本类型)时,我真的应该将不同的相等行为视为不一致吗?

c# .net equality iequalitycomparer iequatable
2个回答
2
投票

对或错,这是我倾向于在基类和派生类上实现Equals(Object)IEquatable<T>.Equals(T)的方式。


0
投票

[今天我问自己,将IEquatable<T>添加到班级中会带来什么后果,我找到了您的问题。然后,我测试了您的代码。对于其他所有人,这是一个答案(而不是“像那样做才能使它起作用”。

© www.soinside.com 2019 - 2024. All rights reserved.