5

我实现了一个 PagedModel 类来包装 IEnumerable,以便为我的 MVC 应用程序中的网格提供分页数据。我使用 Resharper 自动生成的平等代码告诉它检查数据、总行数、页码和页面大小字段。这是课程代码:

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

我发现对 Equals(other._ModelData, _ModelData) 的调用很奇特,因为 AFAIK 会检查它是否是同一个对象,而不是包含的项目是否相同。因为无论如何我的测试都失败了,所以我继续将其更改为 other._ModelData.Equals(_ModelData) 但没有成功。然后我在调试时反映到它,发现 other._ModelData.GetType().GetMethod("Equals",{GetType(Object)}).DeclaringType 是 Object!显然,这将导致比较失败。

我想出了一个解决方案来创建一个 EnumerableEquals 方法,该方法比较两个枚举中的每个项目以确认它们是相同的,但它看起来很草率。我可以做些什么来使用正常的 .Equals 方法吗?

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
4

3 回答 3

5

您可能想使用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

这将确保两个 IEnumerable 具有相同顺序的相同元素。

于 2012-05-23T21:05:23.133 回答
0

您不能真正使用“正常” Equals 方法,因为它没有为可枚举定义(即,它不进行元素比较)。你所拥有的很好 (*),但如果你想使用Equals语法,你可以考虑使用 @StriplingWarrior 建议的。

(*) 您的实现并没有真正检查两者是否相等。如果 'a' 的元素比 'b' 多,它将返回 True;此外,如果 'a' 与 'b' 具有相同的元素,但顺序不同,它也会返回 True。如果这对您的场景来说没问题,那就没问题了。

于 2012-05-23T21:00:35.770 回答
0

通常,对于任意两个任意存储位置X和,除非写入,否则Y的值X.Equals(Y)永远不会改变。虽然不可变集合类型可以覆盖以测试序列相等性,但可变类类型除了测试引用标识(这是默认行为)之外不能做任何事情。XYEqualsEquals(Object)

于 2012-09-24T23:25:04.620 回答