当我比较一个Object(类型)它是否使用特定类的IEquatable?

时间:2011-01-28 17:04:59

标签: c# generics iequatable

我的方法接收两个Object类型的参数。它们具有相同的类型,实现IEquatable

我的问题是:当我这样做时:param1 == param2框架使用特定类的IEquatable运算符覆盖进行比较,还是使用仅比较两个内存指针的object.Equals对象

这是最好的方法吗?是否存在泛型和派生限制?

3 个答案:

答案 0 :(得分:4)

实际上,它既没有。默认情况下,==运算符将测试引用相等性,无论您的Equals方法被覆盖的行为如何(如果您已覆盖它,如果您实现了IEquatable<T>,那么您当然应该拥有该行为)

也就是说,如果您的变量输入为object,但您想使用自己的自定义相等比较,请使用Equals(x, y)而不是x == y

然后,即使您已实施IEquatable<T>,也一定要仍覆盖object.Equals ,如下所示:

class MyType : IEquatable<MyType>
{
    public bool Equals(MyType other)
    {
        // Whatever you want.
    }

    public override bool Equals(object other)
    {
        // Presumably you check for null above.
        return Equals(other as MyType);
    }
}

虽然您确实可以也为您的类型重载==!=运算符,但如果您引用此类型的对象,则无法实现任何操作只需object个变量,就像这样:

object x = new MyType();
object y = new MyType();
Console.WriteLine(Equals(x, y));
Console.WriteLine(x == y);

上面的内容将无法正常工作(如果您已经重载==并期望使用它),因为必须在编译时解析==重载;由于xy被输入为任意对象,因此C#编译器将选择object类型的==运算符,该运算符再次仅测试引用相等性。


更新:现在,可以确保使用==运算符,如果您的变量类型为您定义的类或< / em>更多派生类型。例如,给定以下类型:

class A
{
    public static bool operator ==(A x, A y) { return true; }
    public static bool operator !=(A x, A b) { return false; }
}

class B : A { }

class AComparer<T> where T : A
{
    public bool CompareEqual(T x, T y) { return x == y; }
}

上面的AComparer<T>.CompareEqual方法将使用您重载的==运算符来来自T任何类型A

要记住的关键是==静态,这意味着它的重载解析在编译时执行,而不是在运行时使用vtable执行(除非你是使用dynamic,但这是另一个野兽)。因此,只要您在代码中使用==运算符并且希望重载解析为自定义类型的运算符,就要注意这一点。

答案 1 :(得分:2)

答案 2 :(得分:1)

如果您的方法的参数指定为object,则执行param1 == param2只执行引用相等,因为==运算符不是多态的。