[英]C# Overloading operator ==
//overloading operator ==
class Point
{
private int m_X,int m_Y;
public static operator == (Point p1 ,Point p2)
{
if(object.ReferenceEquals(p1,p2)
return true;
if((object)(p1) == null) || ((object)(p2) ==null)
return false;
return( (p1.x == p2.x) && (p1.x == p2.x));
}
//overloading the != operator
}
如果重载==运算符,通常优先覆盖Equals()方法,因为它们应返回相同的结果,如果不覆盖它,Object.Equals()将推迟到ReferenceEquals(),因此运算符和方法将有不同的结果。 这样做的简单方法是让操作符调用Equals()方法(它应该具有与此处类似的代码)
您必须强制转换为Object来执行== null比较,因为您处于重载的==方法中,因此如果没有强制转换为基类型,您的运算符方法会无休止地调用它来尝试评估p1 == null
。
在Overriding Equals()和operator ==的指南中 ,它说:
operator ==的重载中的常见错误是使用(a == b),(a == null)或(b == null)来检查引用相等性。 这反而导致调用重载的运算符==,导致无限循环。 使用ReferenceEquals或将类型转换为Object,以避免循环。
1)重载.Equals()并不是绝对必要的,但这被认为是良好的编码实践。 您通常不希望.Equals()进行参考比较,运算符==进行值比较。 您还应该重写GetHashCode和operator!=。
2)发生堆栈溢出是因为你一遍又一遍地调用自己的运算符==。 当转换不存在时,编译器有两个选择:
使用你的operator ==(Point,Point)的实现
使用Object的运算符==(对象,对象)
因为#1更具体,所以编译器会选择您的实现。 对对象进行Explicilty强制转换可确保调用Object的operator ==实现。 您可以使用以下代码在没有强制转换的情况下实现相同的目标:
if (Object.Equals(p1, null) || Object.Equals(p2, null))
1 - 没有必要,尽管它会很好。 实际上,您尝试在运算符中实现的行为通常放在Equals方法上。
2 - 如果不进行强制转换,p1 == null将调用运算符本身,从而导致堆栈溢出。
此链接指向重写等于和==的MS准则。
回答你的第一个问题:这在技术上并不是强制性的,但是如果你不重写Equals
,它将执行==
运算符最初做的事情:返回System.Object
版本,它检查引用是否相同。 因此,如果你想让Equals
做与==
相同的事情,你也必须覆盖它。 看看“ 我什么时候应该使用==以及何时应该使用Equals? ”从那篇文章中:
对于尚未重载==的引用类型,它会比较两个引用是否引用同一个对象 - 这正是Equals在System.Object中的实现。
第二个问题的答案是,如果你不将它们强制转换回object
,当你评估p1 == null
时,会对你的==
运算符进行无限递归调用。 看见? 你将在内部调用==
,因为p1是一个Point
,这是Point
类的==
运算符。 相反,您要在该行上执行的操作是确定两个引用是否为null,运算符的System.Object
版本将执行此操作。
堆栈溢出异常可能是因为在p1上使用==
再次无休止地调用你的==
运算符。
在这种情况下覆盖==
运算符是个好主意。
您将受益于进一步研究==
和.Equals()
之间的差异以及Value和Reference类型之间的区别( Point
是一个struct
,意味着它是一个Value类型)。
您当前的覆盖基本上结合了引用和值相等性检查 - 使其结合了==
和.Equals()
的行为。
关于你的第二个问题,你的==
重载调用自身(在重载中使用==
运算符)。 要考虑的另一个方面是Point
是一个值类型,因此永远不能为null
(除非它包含在Nullable<Point>
)。
我同意覆盖==可能是要走的路。 但是你可以通过使它成为struct
而不是class
来清理大量的代码。 你不必担心空检查,它会更符合逻辑,因为它确实是一个“价值”。
正如其他人所说的那样,如果你创建一个==
运算符,则不必严格覆盖.Equals(object o)
,但它是首选的。 此外,如果不这样做,编译器将生成一些警告。
warning CS0660: '<Type>' defines operator == or operator != but does not override Object.Equals(object o)
warning CS0661: '<Type>' defines operator == or operator != but does not override Object.GetHashCode()
因此,即使编译器指向您重写.Equals(Object o)
并且==
defer to that。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.