2

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

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

最好的方法是什么?有泛型和派生约束吗?

4

3 回答 3

4

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

也就是说,如果您的变量类型为 asobject但您想使用自己的自定义相等比较,请使用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);
    }
}

虽然您当然也可以为您的类型重载==and!=运算符,但如果您引用了这种类型的简单object变量的对象,这将不会完成任何事情,如下所示:

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

上面的内容不会像您预期的那样工作(如果您已经重载==并希望使用它),因为==重载必须在编译时解决;因为xy被键入为任意对象,所以 C# 编译器将选择object类型的==运算符,这再次测试引用是否相等。


更新:现在,如果您的变量被键入为您定义它的类更派生的类型,您可以确保使用您的运算符。例如,给定以下类型:==

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将对任何==派生自.TA

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

于 2011-01-28T17:10:42.717 回答
2

您也必须覆盖 Equals,甚至 GetHashCode():看看这里:http: //blogs.msdn.com/b/jaredpar/archive/2009/01/15/if-you-implement-iequatable-t-you -still-must-override-object-s-equals-and-gethashcode.aspx

于 2011-01-28T17:09:36.223 回答
1

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

于 2011-01-28T17:07:44.587 回答