5

MVC アプリのグリッドにページング データを提供するために、IEnumerable をラップする PagedModel クラスを実装しました。Resharper の自動生成された Equality コードを使用して、データ、合計行、ページ番号、およびページ サイズ フィールドをチェックするように指示しました。クラスコードは次のとおりです。

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) への呼び出しは独特であることがわかりました。これは、含まれているアイテムが同じであることではなく、同じオブジェクトであることを確認します。とにかくテストが失敗していたので、先に進み、それを other._ModelData.Equals(_ModelData) に変更しましたが、成功しませんでした。次に、デバッグ時に反映したところ、other._ModelData.GetType().GetMethod("Equals",{GetType(Object)}).DeclaringType が Object であることがわかりました。明らかに、それは失敗した比較になります。

2 つの列挙型のすべての項目を比較して同じであることを確認する 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

これにより、両方の IEnumerables が同じ要素を同じ順序で持つことが保証されます。

于 2012-05-23T21:05:23.133 に答える
0

一般に、任意の 2 つの格納場所Xおよびについて、またはが書き込まれない限りY、 の値はX.Equals(Y)決して変更されません。不変のコレクション型をオーバーライドしてシーケンスの等価性をテストすることは可能ですが、可変クラス型は、参照 ID のテスト (デフォルトの動作) 以外のことを適切に行うことはできません。XYEqualsEquals(Object)

于 2012-09-24T23:25:04.620 に答える
0

Enumerable に対して定義されていない (つまり、要素の比較を行わない) ため、「通常の」 Equals メソッドを実際に使用することはできません。あなたが持っているものは完全に問題ありません (*) が、Equals構文を使用したい場合は、@StriplingWarrior が提案したものを使用することを検討できます。

(*) あなたの実装は、両方が等しいかどうかを実際にはチェックしません。「a」に「b」よりも多くの要素がある場合、True が返されます。また、'a' が 'b' と同じ要素を持ち、順序が異なる場合も True を返します。それがあなたのシナリオで問題なければ、問題ありません。

于 2012-05-23T21:00:35.770 に答える