我的方法接收两个Object
类型的参数。它们具有相同的类型,实现IEquatable
。
我的问题是:当我这样做时:param1 == param2
框架使用特定类的IEquatable
运算符覆盖进行比较,还是使用仅比较两个内存指针的object.Equals
对象
这是最好的方法吗?是否存在泛型和派生限制?
答案 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);
上面的内容将无法正常工作(如果您已经重载==
并期望使用它),因为必须在编译时解析==
重载;由于x
和y
被输入为任意对象,因此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)
你也必须重写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
答案 2 :(得分:1)
如果您的方法的参数指定为object
,则执行param1 == param2
只执行引用相等,因为==
运算符不是多态的。