我的方法接收两个Object
类型的参数。它们具有相同的类型,即实现IEquatable
.
我的问题是:当我这样做时:param1 == param2
框架是使用IEquatable
特定类的运算符覆盖进行比较还是使用object.Equals
仅比较两个对象的内存指针?
最好的方法是什么?有泛型和派生约束吗?
我的方法接收两个Object
类型的参数。它们具有相同的类型,即实现IEquatable
.
我的问题是:当我这样做时:param1 == param2
框架是使用IEquatable
特定类的运算符覆盖进行比较还是使用object.Equals
仅比较两个对象的内存指针?
最好的方法是什么?有泛型和派生约束吗?
实际上,两者都没有。默认情况下,该==
运算符将测试引用相等性,无论您的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);
上面的内容不会像您预期的那样工作(如果您已经重载==
并希望使用它),因为==
重载必须在编译时解决;因为x
和y
被键入为任意对象,所以 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
将对任何==
派生自.T
A
要记住的关键==
是static,这意味着它的重载解析是在编译时执行的,而不是在运行时使用 vtable 执行的(除非你正在使用dynamic
,但那是另一回事)。因此,只要您==
在代码中使用运算符并且希望重载解析为自定义类型的重载,请注意这一点。
您也必须覆盖 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
如果您的方法的参数被指定为object
thenparam1 == param2
只执行引用相等,因为==
运算符不是多态的。