2

I'm doing some LINQ which requires a custom comparer, so I created a new class implementing IEqualityComparer. However, when I use it, I have to create an instance of it each time.

Dim oldListOnly = oldList.Except(newList, New MyEqualityComparer)
Dim newListOnly = newList.Except(oldList, New MyEqualityComparer)

I may be misunderstanding how .NET works, but it seems wasteful to create a new comparer each time. I really just want one instance (the equivalent of static in C++/C#).

So I tried creating a "static" class, which in vb.net is a module. But got an 'Implements' not valid in Modules error.

I then tried making the Equals and GetHashCode function shared methods on my class, but got this error: Methods that implement interface members cannot be declared 'Shared'.

Any ideas how to accomplish my goal here? Or am I simply misunderstanding what's going behind the scenes?

Community
  • 1
  • 1
Jeff B
  • 8,572
  • 17
  • 61
  • 140

3 Answers3

1

Why not simply do

Dim comparer = New MyEqualityComparer
Dim oldListOnly = oldList.Except(newList, comparer )
Dim newListOnly = newList.Except(oldList, comparer )
parapura rajkumar
  • 24,045
  • 1
  • 55
  • 85
  • Indeed. That's the best solution I came up with (although, I was considering making it a private member of the class I'm using it in). However, I remain curious if a shared IEqualityComparer is possible in some way, and if not, why not. – Jeff B Jan 20 '12 at 17:32
1

Your understanding is correct, although the waste is unlikely to be noticeable. For your situation, you could use the singleton pattern, which usually goes something like this:

Public Class MyEqualityComparer
    Implements IEqualityComparer(Of whatever)

    Private Sub New()
        'no outsider creation
    End Sub

    Private Shared ReadOnly _instance As New MyEqualityComparer()
    Public Shared ReadOnly Property Instance As MyEqualityComparer
        Get
            Return _instance
        End Get
    End Property

    'other code

End Class
Gideon Engelberth
  • 6,095
  • 1
  • 21
  • 22
1

There needs to be an instance of a concrete type that implements IEqualityComparer. What you can do with a module, however, is define a public instance which is initialized to "New EqualityComparer". You can then pass that default instance to the Except method.

Something like:

Public Module MyComparer
    Public acmeComparer As acmeCompareType

    Public Class acmeCompareType
        Implements IEqualityComparer(Of System.Drawing.Point)

        Public Function Equals1(x As System.Drawing.Point, y As System.Drawing.Point) As Boolean Implements System.Collections.Generic.IEqualityComparer(Of System.Drawing.Point).Equals
            Return Math.Abs(x.X) = Math.Abs(y.X) AndAlso Math.Abs(x.Y) = Math.Abs(y.Y)
        End Function

        Public Function GetHashCode1(obj As System.Drawing.Point) As Integer Implements System.Collections.Generic.IEqualityComparer(Of System.Drawing.Point).GetHashCode
            ' Note that obj is a struct passed by value, so we can safely modify it here
            ' (without affecting the caller's instance)
            obj.X = Math.Abs(obj.X)
            obj.Y = Math.Abs(obj.Y)
            Return obj.GetHashCode
        End Function
    End Class
End Module
supercat
  • 77,689
  • 9
  • 166
  • 211
  • I ended up going with this, since I have multiple comparers... it worked well to group them all into one module. – Jeff B Jan 26 '12 at 22:36