我一直在尝试实现自定义对象的HashSet,但是从不调用特定于对象的GetHashCode和Equals实现。注意 - 这不是一个学校项目,而是一个数据库清理,几个人完成了部分工作,我需要完成分析。代码在VB.Net下面(VS 2010,2013和2015中也出现同样的问题)
Imports HashSet_testing
Module Module1
Sub Main()
Const Source As String = "the quick brown fox jumped over the lazy red dog"
Dim stringhash As New HashSet(Of String)(Source.Split(" "c))
stringhash.UnionWith(Source.Split(" "c))
Debug.Print(String.Join(" ", stringhash))
Dim WordHash As New HashSet(Of word)
For Each s As String In Source.Split(" "c)
WordHash.Add(New word(s))
Next s
' Second pass; should load nothing
For Each s As String In Source.Split(" "c)
WordHash.Add(New word(s))
Next s
Debug.Print(String.Join(" ", WordHash))
End Sub
End Module
Class word
Implements IEqualityComparer(Of word), IEqualityComparer
Private _word As String = ""
Public Sub New(word As String)
_word = word
End Sub
Public Overrides Function ToString() As String
Return _word
End Function
Public Function Equals1(x As word, y As word) As Boolean Implements IEqualityComparer(Of word).Equals
Debug.Print("Equals({0}, {1} called", x, y)
Return x._word.Equals(y._word)
End Function
Public Function GetHashCode1(obj As word) As Integer Implements IEqualityComparer(Of word).GetHashCode
Debug.Print("GetHashCode1({0}}", obj)
If TypeOf obj IsNot word Then Return 0
Return _word.GetHashCode()
End Function
Private Function Equals2(x As Object, y As Object) As Boolean Implements IEqualityComparer.Equals
Debug.Print("Equals2({0}, {1})", x, y)
If TypeOf x Is word AndAlso TypeOf y Is word Then
Return (Equals1(CType(x, word), CType(y, word)))
Else
Return x.Equals(y)
End If
End Function
Public Function GetHashCode2(obj As Object) As Integer Implements IEqualityComparer.GetHashCode
Debug.Print("GetHashCode2{{0})", obj)
If TypeOf obj Is word Then Return GetHashCode1(obj) Else Return obj.GetHashCode()
End Function
End Class
答案 0 :(得分:0)
如果您想将IEqualityComparer
与HashSet
一起使用,则必须将IEqualityComparer
传递给HashSet
的构造函数。这就是为什么你的方法不在这里调用的原因。
Dim WordHash As New HashSet(Of word)(New word("X"))
根据您的代码编写方式,我认为您可能会将IEqualityComparer(Of T)
与IEquatable(Of T)
混淆。前者通常在您想要更改类的比较方式时使用,而不更改该类本身。例如,如果比较的目标是Word
,那么您将拥有单独的WordEqualityComparer
类。这也是你必须将它传递给HashSet
。
在你的代码中,看起来你真的打算在目标类本身中实现比较逻辑。在这种情况下,您应该覆盖 Equals
类中的基类GetHashCode
和word
方法,并可选择实施IEquatable(Of word)
。如果这样做,则不需要将任何内容传递给HashSet
的构造函数,默认情况下将按预期调用您的方法。
Class word
Implements IEquatable(Of word)
Private _word As String = ""
Public Sub New(word As String)
_word = word
End Sub
Public Overrides Function ToString() As String
Return _word
End Function
Public Function Equals1(w As word) As Boolean Implements IEquatable(Of word).Equals
Debug.Print(String.Format("Equals1({0}) called on {1}", w, Me))
Return Me._word.Equals(w._word)
End Function
Public Overrides Function Equals(obj As Object) As Boolean
Debug.Print(String.Format("Equals({0}) called on {1}", obj, Me))
If TypeOf obj Is word Then
Return Equals1(CType(obj, word))
Else
Return False
End If
End Function
Public Overrides Function GetHashCode() As Integer
Debug.Print(String.Format("GetHashCode() called on {0}", Me))
Return Me._word.GetHashCode()
End Function
End Class