是否有一种快速有效的方法使课程公平?

时间:2014-02-12 10:06:44

标签: vb.net .net-4.0 equality

我有许多类,其中包含primitive typesarray / nullable原始类型的许多属性/字段。

Public Class ClassN
    Public P1 As Integer
    Public P2 As Byte()
    Public P3 As String
    Public P4 As Short?
    '...
    Public P17 As Boolean
    Public P18 As Char()
End Class

此时我已经提出了使用attributes和执行相等性测试的“相等服务类”的解决方案。但是有更快更有效的方法来实现这个吗?

代码

<AttributeUsage((AttributeTargets.Field Or AttributeTargets.Property), AllowMultiple:=False, Inherited:=False)> _
Public Class EquatableAttribute
    Inherits Attribute
End Class

Public Class ClassN
    Implements IEquatable(Of ClassN)

    <Equatable()> Public P1 As Integer
    <Equatable()> Public P2 As Byte()
    <Equatable()> Public P3 As String
    <Equatable()> Public P4 As Short?
    '...
    <Equatable()> Public P17 As Boolean
    <Equatable()> Public P18 As Char()

    Public Overrides Function Equals(obj As Object) As Boolean
        Return Me.Equals(TryCast(obj, ClassN))
    End Function

    Public Overloads Function Equals(obj As ClassN) As Boolean Implements System.IEquatable(Of ClassN).Equals
        Return EqualityServices.Equals(Of ClassN)(Me, obj)
    End Function

End Class

Public NotInheritable Class EqualityServices

    Private Sub New()
    End Sub

    Public Overloads Shared Function Equals(Of T)(obj1 As T, obj2 As T) As Boolean
        If (obj1 Is Nothing) Then
            Return obj2 Is Nothing
        End If
        If (obj2 Is Nothing) Then
            Return False
        End If
        Dim type As Type = GetType(T)
        Dim members As MemberInfo() = Nothing
        If (Not EqualityServices.EquatableAttributeCache.TryGetValue(type, members)) Then
            members = New MemberInfo(-1) {}
            For Each info As MemberInfo In type.GetMembers((BindingFlags.Public Or BindingFlags.Instance))
                If (info.GetCustomAttributes(EqualityServices.EquatableAttributeType, False).Length > 0) Then
                    Select Case info.MemberType
                        Case MemberTypes.Field
                            Exit Select
                        Case MemberTypes.Property
                            With DirectCast(info, PropertyInfo)
                                If ((Not .CanRead) OrElse (.GetIndexParameters().Length > 0)) Then
                                    Continue For
                                End If
                            End With
                            Exit Select
                        Case Else
                            Continue For
                    End Select
                    ReDim Preserve members(members.Length)
                    members(members.Length - 1) = info
                End If
            Next
            EqualityServices.EquatableAttributeCache.Add(type, members)
        End If
        If (members.Length > 0) Then
            Dim value1 As Object = Nothing
            Dim value2 As Object = Nothing
            For Each info As MemberInfo In members
                Select Case info.MemberType
                    Case MemberTypes.Field
                        With DirectCast(info, FieldInfo)
                            type = .FieldType
                            value1 = .GetValue(obj1)
                            value2 = .GetValue(obj2)
                        End With
                        Exit Select
                    Case MemberTypes.Property
                        With DirectCast(info, PropertyInfo)
                            type = .PropertyType
                            value1 = .GetValue(obj1, Nothing)
                            value2 = .GetValue(obj2, Nothing)
                        End With
                        Exit Select
                    Case Else
                        Continue For
                End Select
                If (type.BaseType Is EqualityServices.ArrayType) Then
                    If (Not EqualityServices.SequenceEqual(CType(value1, Array), CType(value2, Array))) Then
                        Return False
                    End If
                Else
                    If (Not Object.Equals(value1, value2)) Then
                        Return False
                    End If
                End If
            Next
            Return True
        End If
        Return False
    End Function

    Private Shared Function SequenceEqual(ByVal array1 As Array, array2 As Array) As Boolean
        If (array1 Is Nothing) Then
            Return array2 Is Nothing
        End If
        If (array2 Is Nothing) Then
            Return False
        End If
        If (array1.Rank <> array2.Rank) Then
            Return False
        End If
        If (array1.Length <> array2.Length) Then
            Return False
        End If
        Dim length As Integer = (array1.Length - 1)
        If (length > -1) Then
            Dim list1 As IList = CType(array1, IList)
            Dim list2 As IList = CType(array2, IList)
            For index = 0 To length
                If (Not Object.Equals(list1.Item(index), list2.Item(index))) Then
                    Return False
                End If
            Next
        End If
        Return True
    End Function

    Private Shared ReadOnly EquatableAttributeCache As New Dictionary(Of Type, MemberInfo())
    Private Shared ReadOnly EquatableAttributeType As Type = GetType(EquatableAttribute)
    Private Shared ReadOnly ArrayType As Type = GetType(Array)

End Class

1 个答案:

答案 0 :(得分:1)

ReSharper可以为您生成相关的EqualsGetHashCode等或IEqualityComparer代码。

你只需要ReSharper。

这是一个例子(它是C#,因为我手边只有C#-Edition of ReSharper):

enter image description here

enter image description here

enter image description here