I implemented a PagedModel class to wrap around IEnumerable to provide paging data for grids in my MVC app. I used Resharper's auto-generated Equality code telling it to check the data, total rows, page number, and page size fields. Here's the class code:
Public Class PagedModel(Of T)
Public Property PageSize As Integer
Public Property PageNumber As Integer
Public Property ModelData As IEnumerable(Of T)
Public Property TotalRecords As Integer
Public Overloads Function Equals(ByVal other As PagedModel(Of T)) As Boolean
If ReferenceEquals(Nothing, other) Then Return False
If ReferenceEquals(Me, other) Then Return True
Return other._PageSize = _PageSize AndAlso other._PageNumber = _PageNumber AndAlso Equals(other._ModelData, _ModelData) AndAlso other._TotalRecords = _TotalRecords
End Function
Public Overloads Overrides Function Equals(ByVal obj As Object) As Boolean
If ReferenceEquals(Nothing, obj) Then Return False
If ReferenceEquals(Me, obj) Then Return True
If Not Equals(obj.GetType(), GetType(PagedModel(Of T))) Then Return False
Return Equals(DirectCast(obj, PagedModel(Of T)))
End Function
Public Overrides Function GetHashCode() As Integer
Dim hashCode As Long = _PageSize
hashCode = CInt((hashCode * 397) Xor _PageNumber Mod Integer.MaxValue)
If _ModelData IsNot Nothing Then hashCode = CInt(((hashCode * 397) Xor _ModelData.GetHashCode()) Mod Integer.MaxValue)
hashCode = CInt((hashCode * 397) Xor _TotalRecords Mod Integer.MaxValue)
Return CInt(hashCode Mod Integer.MaxValue)
End Function
End Class
I found the call to Equals(other._ModelData, _ModelData) peculiar, as AFAIK, this checks that it is the same object rather than that the contained items are the same. Because my tests were failing anyways, I went ahead and changed it to other._ModelData.Equals(_ModelData) with no success. Then I reflected into it at debug time and found that other._ModelData.GetType().GetMethod("Equals",{GetType(Object)}).DeclaringType was Object! Obviously, that would result in the failed comparison.
I came up with a solution to create a EnumerableEquals method which compares every item in the two enumerables to confirm the are the same, but it seems sloppy. Is there anything I can do to use the normal .Equals method?
Private Function EnumerableAreEqual(ByVal a As IEnumerable(Of T), ByVal b As IEnumerable(Of T)) As Boolean
b = b.ToList() 'avoid multiple query execution
Return a.All(Function(item) b.Contains(item))
End Function
You probably want to use SequenceEqual.
(new[]{1,2,3}).SequenceEqual(new[]{1,2,3}) // True
(new[]{1,2,3}).SequenceEqual(new[]{3,2,1}) // False
(new[]{1,2,3}).SequenceEqual(new[]{1,2}) // False
(new[]{1,2}).SequenceEqual(new[]{1,2,3}) // False
This will ensure that both IEnumerables have the same elements in the same order.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With