Question

I have some code with two lists of objects. The first list is more inclusive than the second list. I wish to exclude items in the second list from the first list. After some research I found that the extension method Except is the way to do this. I therefor implemented IEquatable(Of T) and IEqualityComparer(Of T) in my code for something like this:

Partial Public Class CustomerData
    Implements IEquatable(Of CustomerData)
    Implements IEqualityComparer(Of CustomerData)

    Public Overloads Function Equals(other As CustomerData) As Boolean Implements IEquatable(Of ToolData.CustomerData).Equals
        If other Is Nothing Then
            Return False
        Else
            Return Me.CustomerID = other.CustomerID
        End If
    End Function

    Public Overloads Function Equals(this As CustomerData, that As CustomerData) As Boolean Implements IEqualityComparer(Of ToolData.CustomerData).Equals
        If this Is Nothing OrElse that Is Nothing Then
            Return False
        Else
            Return this.CustomerID = that.CustomerID
        End If
    End Function

    Public Overloads Function GetHashCode(other As CustomerData) As Integer Implements IEqualityComparer(Of ToolData.CustomerData).GetHashCode
        If other Is Nothing Then
            Return CType(0, Integer).GetHashCode
        Else
            Return other.CustomerID.GetHashCode
        End If
    End Function

I then make a simple call like such:

customerCollection = CustomerData.LocalCustomers.Except(CustomerData.RecentCustomers).OrderBy(Function(x) x.FullName).ToList

This doesn't work. Neither does this:

customerCollection = CustomerData.LocalCustomers.Except(CustomerData.RecentCustomers, EqualityComparer(Of CustomerData).Default).OrderBy(Function(x) x.FullName).ToList

However, this does work:

customerCollection = CustomerData.LocalCustomers.Except(CustomerData.RecentCustomers, New CustomerData).OrderBy(Function(x) x.FullName).ToList

Since RecentCustomers and LocalCustomers are both List(Of CustomerData) why wouldn't the default compare method work? When I say it doesn't work I mean that I can put break points in the Equals and GetHashCode routines and they are never hit and the list returned is identical to the list of LocalCustomers.

Was it helpful?

Solution

First, you don't need to implement the IEqualityComparer(Of T) interface; you would normally implement that in another class if you wanted to provide multiple types of equality for the same class.

Second, you'll need to override the GetHashCode and Equals(Object) methods:

Partial Public Class CustomerData
   Implements IEquatable(Of CustomerData)

   Public Override Function GetHashCode() As Integer
      Return CustomerID.GetHashCode()
   End Function

   Public Override Function Equals(ByVal obj As Object)
      Return Equals(TryCast(obj, CustomerData))
   End Function

   Public Overloads Function Equals(other As CustomerData) As Boolean Implements IEquatable(Of ToolData.CustomerData).Equals
      If other Is Nothing Then
         Return False
      Else
         Return Me.CustomerID = other.CustomerID
      End If
   End Function

   ...

Here's a blog post which explains why: http://blogs.msdn.com/b/jaredpar/archive/2009/01/15/if-you-implement-iequatable-t-you-still-must-override-object-s-equals-and-gethashcode.aspx

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top