This is probably down to the specifics of the Client class. Do the original code and the generic method actually call the same Equals method?
You could have a problem if the Client class implements value equality via IEquatable without also overriding the Object.Equals method. If this is the case then the generic method would be making a reference comparison via Object.Equals.
The IEquatable interface declares a strongly typed Equals method. When used it is important to make sure that the new IEquatable.Equals method and the existing Object.Equals method both give the same result. The code example shows how that can be done and I've set it up so that Client objects are considered equal if their Identity properties return the same value.
Public Class Client
Implements IEquatable(Of Client)
Private id As Int32
Public ReadOnly Property Identity() As Int32
Public Function Equals(other As Client) As Boolean
If ReferenceEquals(other, Nothing) Then
If ReferenceEquals(Me, other) Then
If other.GetType() <> Me.GetType() Then
Return Me.Identity = other.Identity
Public Overrides Function Equals(other As Object) As Boolean
Return Me.Equals(TryCast(other, Client))
Private Function ListEquals(Of T As IEquatable(Of T))(list1 As List(Of T), list2 As List(Of T)) As Boolean
Dim same As Boolean = list1.Count = list2.Count
Dim i As Int32 = 0
While same AndAlso i < list1.Count
same = list1(i).Equals(list2(i))
i += 1
The constraint on the ListEquals method specifies that T must implement IEquatable and most importantly allows the generic method to use the new Equals method.
Without the constraint the comparison method would not know that IEquatable.Equals existed and it could only use Object.Equals. With my implementation of Client this wouldn't matter as my IEquatable.Equals and my Object.Equals have been coded to give the same result.