3

我看到了这里提出的问题:我是否正确实现了 Equals()/GetHashCode()?但是我的 c# 没有那么强大,而且我对 IEquatable 不够熟悉,如果可能的话,我想在 VB.NET 中看到它。

我的示例代码(当我到达那里时,该类最终将使用 INotifyPropertyChanged):

Public Class Car
Implements ICloneable
Implements IEquatable(Of Car)

Public Property Make() As String
    Get
        Return m_Make
    End Get
    Set(ByVal value As String)
        m_Make = value
    End Set
End Property
Private m_Make As String

Public Property Model() As String
    Get
        Return m_Model
    End Get
    Set(ByVal value As String)
        m_Model = value
    End Set
End Property
Private m_Model As String

Public Function Clone() As Object Implements System.ICloneable.Clone
    Return New Car() With { _
     .Make = Me.Make, _
     .Model = Me.Model _
    }
End Function

Public Overloads Function Equals(ByVal other As Car) As Boolean Implements System.IEquatable(Of Car).Equals
    Return other.Make = Me.Make AndAlso other.Model = Me.Model
End Function 
End Class

谢谢,

4

2 回答 2

4

您确实需要为 object.Equals 和 object.GetHashCode 实现实现 Overrides。

基本上,只要调用者知道调用 IEquatable(of T).Equals 而不是常规的 object.Equals,单独实现 IEquatable(of T).Equals 就可以工作。

考虑您是否有一个 Cars ArrayList 并检查列表是否包含(myCar),其中 myCar 的 Make 和 Model 与 ArrayList 中的汽车相同......但 ArrayList 中的汽车实际上并不是完全相同的实例。包含将返回 false。

更糟糕的是,如果您有一个 Hashtable 或 Dictionary,它使用 GetHashCode 来确定存储条目的位置,那么相等将永远不会起作用,因为具有相同 Make 和 Model 的两辆汽车将为 GetHashCode() 返回不同的值

基本上,它归结为您将以下实现添加到汽车:

Public Overrides Overloads Function Equals(obj As Object) As Boolean
    Return TypeOf obj Is Car AndAlso Equals(DirectCast(obj, Car)) 
End Function 

Public Overrides Function GetHashCode() As Int32
    Dim hash As Int32 = 179 ' or something intelligent

    hash = hash * 27 + Make.GetHashCode()
    hash = hash * 27 + Model.GetHashCode()

    Return hash
End Function

所以我的问题是:为什么要实现 IEquatable 呢?为什么不直接覆盖 Equals 和 GetHashCode?

于 2012-03-18T08:17:26.793 回答
1

IEquatable<T>为结构或密封类实现。任何合法的实现都IEquatable<T>.Equals(T)需要具有与类的覆盖兼容的语义Object.GetHashCode(),而后者又必须具有与类的覆盖兼容的语义Equals(Object)。如果一个类型不是密封的,那么确保派生类型的实现IEquatable<T>.Equals(T)与它们的覆盖兼容的唯一方法是Object.Equals(Object)将前一个方法链接到后者,从而有效地抵消一个人可能从IEquatable<T>第一个实现中获得的任何优势地方。

对于结构类型来说,实现IEquatable<T>通常是一个巨大的胜利(在每次比较中保存一个装箱操作),而对于其他密封类型来说是一个较小的胜利(在每次比较中保存一个类型转换)。除非性能至关重要,否则对于大多数非结构类型,我可能会跳过它,即使它们是密封的。

于 2012-03-19T22:42:04.597 回答