C# 当我比较一个对象(类型)时,它是否使用特定类的IEquatable?
我的方法接收两个参数,都是C# 当我比较一个对象(类型)时,它是否使用特定类的IEquatable?,c#,generics,iequatable,C#,Generics,Iequatable,我的方法接收两个参数,都是Objecttype。它们具有相同的类型,实现了IEquatable 我的问题是:当我这样做时:param1==param2框架是使用特定类的IEquatable操作符重写进行比较,还是使用只比较两个对象的内存指针的对象 哪种方法最好?是否具有泛型和派生约束?如果方法的参数指定为对象,则执行param1==param2只执行引用相等,因为=运算符不是多态的。您也必须重写等于,甚至是GetHashCode():请看这里: 事实上,两者都没有。默认情况下,=操作符将测试引用
Object
type。它们具有相同的类型,实现了IEquatable
我的问题是:当我这样做时:param1==param2
框架是使用特定类的IEquatable
操作符重写进行比较,还是使用只比较两个对象的内存指针的对象
哪种方法最好?是否具有泛型和派生约束?如果方法的参数指定为对象
,则执行param1==param2
只执行引用相等,因为=
运算符不是多态的。您也必须重写等于,甚至是GetHashCode():请看这里:
事实上,两者都没有。默认情况下,=
操作符将测试引用相等,而不管您的Equals
方法的重写行为如何(如果您已经重写了它,如果您实现了IEquatable
,那么您当然应该拥有它)
也就是说,如果变量类型为object
,但您希望使用自己的自定义相等比较,请使用Equals(x,y)
,而不是x==y
然后,即使您已经实现了IEquatable
,也要确保仍然覆盖对象。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 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; }
}
A类
{
公共静态布尔运算符==(ax,ay){返回真;}
公共静态布尔运算符!=(ax,ab){返回false;}
}
B类:A{}
A类比较者,其中T:A
{
公共布尔比较相等(tx,ty){return x==y;}
}
上面的A comparer.CompareEqual
方法将对从A
派生的任何类型T
使用重载的=
运算符
要记住的关键是=
是静态的,这意味着它的重载解析在编译时执行,而不是在运行时使用vtable执行(除非您使用的是动态
,但这完全是另一回事)。因此,只要注意,当您在代码中使用==
运算符时,您希望重载解析为自定义类型的重载。并且如果在我的方法中使用派生约束,请注意这一点。这有什么变化吗?“我不能重载像equals这样的对象的操作符?”蒂亚戈:对不起,我不知怎么错过了你之前的评论。我想我理解你的要求;给我几分钟时间更新我的答案。@Thiago:对不起,我完全忘记了那个评论,直到现在。查看我的更新,让我知道它是否回答了您的问题!