回复:深入解析.NET的相等操作符
哈希码下一步是产生哈希码。最简单的方法是将所有用于相等性比较的成员变量的哈希码作异或运算。

Code
C#
public override int GetHashCode()
{
return _X.GetHashCode() ^ _Y.GetHashCode();
}
VB
Public Overrides Function GetHashCode() As Integer
Return m_X.GetHashCode Xor m_Y.GetHashCode
End Function
如果你确实决定要从头写自己的哈希码,你必须确保对于一套给定的值,你总是能返回相同的哈希码。换言之,如果a等于b,那么它们的哈希码也相等。
哈希码不必是唯一的,不同的值可以有相同的哈希码。但是它们应该有一个良好的分布。对于每一个哈希码都返回42在技术上是合法的,但是任何使用该算法的应用在性能上都会很糟糕。
哈希码应该以非常快的速度计算出来。由于计算哈希值可能成为瓶颈,所以宁可选用一个快速的有合理良好分布的哈希码算法,而不选择一个慢的,复杂的有着完美的均匀分布的算法。
相等(对象)重写基类的Equals方法是一个基础工作,该方法被Object.Equals(Object, Object)函数和其他方法调用。
你应该注意到由于类型转换做了两次,所以可能存在一点性能问题:一次是看它是否有效,第二次是真正的执行它。不幸的是,在结构中是无法避免这样作的。

Code
C#
public override bool Equals(object obj)
{
if (obj is PointStruct)
{
return this.Equals((PointStruct)obj);
}
return false;
}
VB
Public Overrides Function Equals(ByVal obj As Object) As Boolean
If TypeOf obj Is PointStruct Then Return CType(obj, PointStruct) = Me
End Function
对于类可以只用一次类型转换。在处理步骤中,我们可以早点检测空值然后跳过对Equals(PointClass)方法的调用。C#必须用ReferenceEquals函数来检查空值。
为了防止子类破坏相等性,我们封闭(Seal)了方法。

Code
C#
public sealed override bool Equals(object obj)
{
var temp = obj as PointClass;
if (!Object.ReferenceEquals(temp, null))
{
return this.Equals(temp);
}
return false;
}
VB
Public NotOverridable Overrides Function Equals(ByVal obj As Object) As Boolean
Dim temp = TryCast(obj, PointClass)
If temp IsNot Nothing Then Return Me.Equals(temp)
End Function
操作符重载所有的难题都被攻克了,我们现在可以进行操作符的重写了。这里和调用类型安全的Equlas方法一样简单。

Code
C#
public static bool operator ==(PointStruct point1 PointStruct point2)
{
return point1.Equals(point2);
}
public static bool operator !=(PointStruct point1, PointStruct point2)
{
return !(point1 == point2);
}
VB
Public Shared Operator =(ByVal point1 As PointStruct, ByVal point2 As PointStruct) As Boolean
Return point1.Equals(point2)
End Operator
Public Shared Operator <>(ByVal point1 As PointStruct,
ByVal point2 As PointStruct) As Boolean
Return Not (point1 = point2)
End Operator
对于类,需要检查空值。幸运的是,Object.Equals(object, object)为你处理了这种情况。然后调用已经被重写的Object.Equals(Object)方法。

Code
C#
public static bool operator ==(PointClass point1, PointClass point2)
{
return Object.Equals(point1, point2);
}
public static bool operator !=(PointClass point1, PointClass point2)
{
return !(point1 == point2);
}
VB
Public Shared Operator =(ByVal point1 As PointClass, ByVal point2 As PointClass) As Boolean
Return Object.Equals(point1 ,point2)
End Operator
Public Shared Operator <>(ByVal point1 As PointClass, ByVal point2 As PointClass) As Boolean
Return Not (point1 = point2)
End Operator
性能你会注意到每个调用链都有点长,尤其是不相等操作符。如果需要考虑性能问题,你可以分别在每个方法中实现比较逻辑来提高速度。这样很容易出错而且使得维护工作比较辣手,所以仅仅当你使用性能检测工具证明了必须这样作之后,才应该这样作。